Slots in layers, was Re: [closer-devel] ContextL design question...

Pascal Costanza pc at p-cos.net
Thu Mar 2 16:07:38 UTC 2006


Hi Nick and everyone else,

On 28 Feb 2006, at 22:06, Pascal Costanza wrote:

> On 28 Feb 2006, at 20:48, Nick Bourner wrote:
>
>> Thanks for that, I'll give it a try.
>>
>> Is the value of the slot global or can it be set on a per-thread  
>> basis
>> like active layers? I was thinking that it could be a good way of
>> carrying information for a particular activation of a layer. Say, for
>> instance, a stream for a display layer to write to or something. Then
>> you could have something like
>>
>> (with-active-layers ((some-layer :some-slot a-value) some-other- 
>> layer)
>>    ...)
>> or
>> (ensure-active-layer (some-layer :some-slot a-value))
>>
>> rather than something like
>>
>> (let ((*some-special* a-value))
>>   (with-active-layers (some-layer some-other-layer)
>>     ....
>>
>> Not a whole lot different but I think it just expresses the intent
>> slightly more clearly.
>
> Now, that's a very neat idea, especially the syntax. And I think it  
> should be possible to implement this in a relatively  
> straightforward way.

The darcs repository now contains a new version of ContextL that  
supports this, with some slight differences though.

You can now define layers like this:

(deflayer some-layer ()
   ((slot1 :initform 'foo :reader slot1)
    (slot2 :initform 'bar :special t :accessor slot2)))

Since layers are singletons (I referred to this previously as the  
"prototype model"), you cannot associate an :allocation other  
than :class with a slot. If you don't specify :allocation, it will  
automatically be :class. Since you cannot make instances of a layer,  
you cannot specify any :initarg options either.

Slots in layers can be :special, like in the metaclass special-class.  
(The :special option now also works correctly  
with :allocation :class, I hope - there was a bug in the special- 
class implementation in that regard that I have fixed.)

I haven't extended the with-active-layers construct, though. Here are  
the reasons:
- It would really only look neat when used with initargs instead of  
accessors. However, the mapping of initargs to actual slots can be  
changed at runtime in CLOS, so I would have to emit code with quite  
some overhead here that would determine the current mapping of an  
initarg to its actual slot. Worse, an initarg could actually be  
mapped to more than one slot, which would complicate the code even  
further, with very little reward. I wanted to avoid that.

Therefore, if you want to switch layers and then also rebind slots in  
layers, you have to express it as follows:

(with-active-layers (some-layer)
   (dletf (((slot1 (find-layer 'some-layer)) 42))
     ...))

I hope this is neat enough. ;)

Ah, yes, you don't need to say (layer-prototype (find-layer 'some- 
layer)) here.

The singleton stuff is actually implemented in a metaclass singleton- 
class. So you can also create singleton classes like this:

(defclass some-singleton-class ()
   ((some-slot :initform 'baz :reader some-slot))
   (:metaclass singleton-class))

...and then you can access the slot also by saying (some-slot (find- 
class 'some-singleton-class)) or (slot-value (find-class 'some- 
singleton-class) 'some-slot). Singleton classes don't support special  
slots by themselves, you have to mix them with the metaclass special- 
class to get both functionalities.

Please don't say find-class in conjunction with layers - this won't  
work!

OK, I hope this will all work for you. Feel free to ask any questions...


Cheers,
Pascal

-- 
Pascal Costanza, mailto:pc at p-cos.net, http://p-cos.net
Vrije Universiteit Brussel, Programming Technology Lab
Pleinlaan 2, B-1050 Brussel, Belgium







More information about the closer-devel mailing list