Re: there is a subtle problem doing: mySlot := obj getSlot(slotname)

Jeremy Tregunna <[email protected]>
Newsgroups gmane.comp.lang.io
Message-ID <[email protected]>
On 2011-11-08, at 6:48 AM, gatesphere wrote:

> 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 he wants to be able to perform some kind of analysis on the object returned on the first line in the method.

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.

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 works for me.
> 
> -->Jake
> 
> On 11/8/2011 7:30 AM, Mildred Ki'Lya wrote:
> 
>>  
>> Hi,
>> 
>> I like static typing a lit, and I thought ... why not implement a layer of static typing in Io directly. I could run a compilation stage just before running the main program and check typing errors using the wonderful Io introspection features. Note: this is my code that I write in Io.
>> 
>> At some point, I need to check a method implementation against an interface. To do that, I need to find the method implementation in an object. To do that, i'm using getSlot to do something like:
>> 
>>   checkObjectMessage := method(obj, slotname, returnInterface, args,
>>     # Find the message implementation
>>     slot := obj getSlot(slotname)
>>     "name: " print; slotname print; "." println
>>     "slot: " print; obj getSlot(slotname) print; "." println
>>     "slot: " print; slot print; "." println
>>     # TODO: iterate over all instructions, and check each instruction is legal
>>     self
>>   )
>> 
>> You can see few print messages ... this is for debug. When I run this code, I get a difference between the first "slot:" printed line, and the second "slot:" printed line. The first displays the code of the method, something like:
>> 
>> slot: 
>> # /home/shanti/Perso/io/libs/iovm/io/A2_Object.io:461
>> method(
>>     getSlot("self") print; write("\n"); getSlot("self")
>> )
>> .
>> 
>> This is expected. But then the second line shows:
>> 
>> slot: Object_0x98778f8 do(
>>   appendProto(Object_0x985c7a0)
>> 
>> Object_0x98778f8 do(
>>   appendProto(Object_0x985c7a0)
>> .
>> 
>> Apparently the local variable "slot" is being assigned to a method ... and whel looking up this variable, the method is called. I suppose I should do getSlot("slot") to do the trick. I was wondering if there was a way to store a Block object in a variable, and be able to access this variable in any other way than getSlot("varname").
>> 
>> And, I think this should be added to the pitfalls page, unless I missed something.
>> 
>> Thank you,
>> 
>> Mildred
>> 
>> -- 
>> Mildred Ki'Lya
>> http://mildred.fr
> 
> 
> 

Regards,

Jeremy Tregunna
I'm available via e-mail at [email protected], or facetime at [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.