[e-lang] Re: On kernel-E, operators, and properties (part 1)

David Hopwood david.nospam.hopwood at blueyonder.co.uk
Thu Apr 8 18:50:01 EDT 2004


Miller, Mark wrote:
> David Hopwood wrote:
> 
>>>  expr1<-name := expr2  -->  expr1<-&name<-setValue(expr2)
>>
>>This expansion has some consequences I hadn't considered. The two
>>send operations in the expanded code are not atomic, so if it is
>>possible for a given property slot to change to a different slot
>>object, updates could be lost:
>>[...]
>>Also, it's difficult to see why you would want to change the slot of
>>an existing property. Even upgrading the slot implementation does not
>>require this.
> 
> I agree that wanting this would be exceedingly rare, but we do have one
> example of essentially the same issue, and a (possibly kludgy but working) 
> way in which we handle this one case:
> 
> The top level interactive scope allows old variable names to be rebound
> to new Slots, independent of whether those Slots allow themselves to be
> mutated. However, closures over top level names must continue to
> effectively capture the binding of the name in such a way as stay bound
> across both types of change. This enables an intuitive style of incremental
> development: [snip]

I agree this is how the toplevel should work. I hadn't realised that the
ML toplevel does it differently.

[...]
> We do not implement this by introducing a separate mechanism to allow
> closures to capture names rather than slots. Rather, when foo is defined,
> it obtains a Slot at that time corresponding to its free use of the name
> "factorial", and it remembers this Slot.
> 
> So where do we put the special case supporting this strange interactive
> environment? In the mutable (interactive) outer scope object itself. When
> it's asked for a Slot object for "factorial", it doesn't return the
> current Slot that this name is bound to, since (uniquely to a mutable
> outer scope), that binding may change. Instead, it returns a ForwardingSlot
> that delegates essentially all of its behavior to the current Slot
> bound to its variable:

Yep, that's how I would do it. Assuming the obvious implementation of a
ForwardingSlot (where the slot variable is near and gets changed by a method,
say 'rebind', of ForwardingSlot), it doesn't have the problem described in
my previous post, because rebind cannot be called at the same time as
getValue or setValue.

The problem only occurs if there is actually a new slot object (as opposed
to a fixed forwarder), *or* if the slot that is forwarded to can change
asynchronously with respect to calls to getValue or setValue. The latter
would arguably be a bug in the forwarder implementation (and given E's
approach to concurrency, not a very likely bug).

>     ? def fSlot := &factorial
>     # value: <forwards to: <& <factorial>>>
>     
>     ? var factorial := 37
>     # value: 37
>     
>     ? foo(3)
>     # problem: <NoSuchMethodException: <an Integer>.run/1>
> 
> Yes, by changing factorial to a different kind of thing, we broke foo.

That's not a bug, it's a feature :-) Having foo still work would be even
more surprising.

> For good or ill, ML would prevent us from being able to have problems like this.
> 
>     ? &factorial
>     # value: <forwards to: <& 37>>
>     
>     ? fSlot.getValue()
>     # value: 37
> 
> This technique could be generalized to the case you raise above. In those
> rare circumstances where the name-to-Slot binding is itself settable, the
> __getSlot/1 method could return a stable ForwardingSlot that forward to
> whatever the most recently set Slot is.

Right, subject to the caveat above about rebinding the slot asynchronously.
I think this just confirms that there is no real problem, and the expansions
I suggested would be fine.

David Hopwood <david.nospam.hopwood at blueyonder.co.uk>



More information about the e-lang mailing list