Re: there is a subtle problem doing: mySlot := obj getSlot(slotname)
"Mildred Ki'Lya" <[email protected]>
| Newsgroups | gmane.comp.lang.io |
|---|---|
| Message-ID | <CAHU8KxjsXXTvyDzRr9osi_cLsi8VuQrPu8xOwuYYuuYPawDoEQ@mail.gmail.com> |
> > Try this: > checkObjectMessage := method(obj, slotname, > slot := obj getSlot(slotname) asString; > "name: " print; slotname print; "." println; > "slot: " print; obj getSlot(slotname) print; "." println; > "slot: " print; slot print; "." println; > self > ) > > That doesn't have the same effect. Perhaps she wants to be able to perform > some kind of analysis on the object returned on the first line in the > method. > That's right, I don't want to transform the object to a string. Anyway, the solution is to call getSlot ... that's not so much of a problem anyway. > The problem with what the OP is trying to do is that we store the > activation bit on objects themselves. This means, that when you get a > reference to the object, it retains its activation bit (it has to, > otherwise we break code). We could have implemented this differently in the > core, but we didn't. As such, when you use getSlot() you get a reference to > the object itself, activation bit set and all. The way the evaluator > (perform()) works is basically this: > > 1. Check if there's a cached result on the message > 1a. Return it if so > 2. Look up the message name on the receiver > 2a. If we find it, go to 4. > 2b. If we don't find it, call forward. > 2c. If we exhaust our parents and still can't find the slot, throw an error > 3. Call the method, return the result. > 4. Check its activatable bit. > 4a. If set, go to 2, but look up "activate" > 5. If all else fails, return our value (unactivated). > > There's really nothing more to the evaluator. There are minor variations > you can make on the evaluator, but by and large that's the general > algorithm. > > For Acute, I had, for a while, introduced an intermediate object called a > "Slot" which was stored in the slot table. This Slot object had a reference > to the actual value held in, as well as the activation bit. If in the OP > case, when the slot := ... assignment occurs, a new Slot object gets > created, with the referenced value held it its data slot, without the > activation bit set. Which means when you try and call it by name, instead > of activating you'd get the actual Block object. This is not an algorithm > chosen by the mainline Io implementation, and actually one I've abandoned > for Acute. > > This is a common gotcha, and a source of many pains if you are writing > library code. You can never be sure if a user is passing in an activatable > object, so you have to account for that. > Is it so much a problem in library code, can't we assume that we don't accept method objects? > > If this isn't mentioned somewhere, it should be. That said, perhaps it's > time we figured out a long term solution to this problem which doesn't > affect performance quite as much as my Slot object idea did (impacted the > runtime by approximately 35% of additional overhead). > That's not an easy solution ... For a long time (before I knew about Self and Io), i tried to design a language that had methods as first-class objects. I never really succeeded. Perhaps we should look at how Self or NewtonScript can do that. I admit I never looked long enough to grasp this kind of details. Now, if I think about it, what is that exactly that we want? We want to: - (1) be able to mix methods and data in slots. Methods slots being called, and data slots being taken as they are - (2) pass blocks as arguments and have them called when the value is required - am i missing something there? To solve (1), the best solution I can think of is to store alongside with the slot name in the object, a boolean telling if the object has to be activated. But how do we set this boolean value? We can either use a different operator (Lisaac, and perhaps Self, uses := for data slots and <- for code slots) As for (2), the purpose is for the block to be transparent, and behave just as the value it would return. So, we want to keep the perform step just as it is and keep the activation bit in the object. To sum this up, blocks objects keep their activation bits, but we add another activation bit with the slot name in objects. When we lookup a slot, if either the slot or the object have the activation bit set, the activation step is performed. Methods would have the activation bit in the slot and Blocks would have the activation bit in the block object. By the way, a few weks ago I expressed my interest in the acute project, and my desire to contribute. But I don't. I'm sorry about that but that's because I can't understand the roadmap and the desired architecture of acute. I'm still following the commits with much interest. Mildred -- Mildred Ki'Lya http://mildred.fr