[self-interest] Closure/method discrepancy...

Jecel Assumpcao Jr jecel at merlintec.com
Thu Dec 20 21:50:03 UTC 2001


> Firstly, I have no problem with the cloning of the activation
> records, etc.  That makes total sense.

Ok. One complaint some people have about the "cloning" is that the 
methods don't have ':self*' slots but activation records do. I guess 
these slots (note that they are argument and parent) could be added to 
methods to make things more uniform while wasting a little space.

But actually, activation records are continuations and not just 
closures. They have an instruction pointer and a local data stack, 
neither of which was in the original method object.

In some of my implementations I have dealt with this by slightly 
redefining the "method story". The method is indeed a prototype for the 
closure, but when it is cloned a second object is also cloned and 
installed at its parent:

       ( | :self*.
            <pc> <- 0.
            <stk> <- vector copySize: 16 FillingWith: 0.
            <sp> <- 0.
        | )

where <name> indicates a slot name that can't be accessed via normal 
message sends. This object plus the cloned method would form an 
activation record.

> I do have issues with lexical scoping in interpreted environments
> generally, and especially with pure object-oriented languages.  Other
> than the lexical issues, self is a clear gem.

I created a Self-like language, NeoLogo, with dynamic scopes. It is 
cleaner, but gets the programmers into trouble more easily.

> My problem starts with self curtailing the lifespan of closures to
> the enclosing method.  Although it saves the implementation from
> dealing with moving activation records off the stack, it cripples the
> language.  I very much like the idea of passing closures around and
> sticking them into slots.

Here is a quote from "Towards a Universal Implementation Substrate for 
Object-Oriented Languages" by Mario Wolczko, Ole Agesen, David Ungar:

"Life-time of blocks. Self blocks cannot be invoked after their 
enclosing method returns. Lifting this restriction makes it easier to 
translate Smalltalk blocks that use this feature, as well as 
translating other languages with closure-like constructs."

> Also, at the risk of getting off-topic, I need to get to the bottom
> of the closure/method issue.  Once again, apologies for not being up
> on self.  This is the way I envision the ideal OO language (and self
> is really close...)
>
> 1) There is an environment supporting objects.
> 2) Objects contain slots and a piece of code.

Either one can be missing in a given object, though.

> 3) Each slot consists of a name and a pointer to another object.  The
> name dynamically binds the referenced object and allows code to refer
> to it.
> 4) The code is in some manner human-modifiable and executable by the
> machine (ignore implementation details here).
> 5) Through code, the environment can modify both the shape of an
> object (number and naming of slots) as well as the contents of the
> slots.

One major decision is how common this will be. If "normal" code doesn't 
do this, but only the IDE as a result of a direct request by the 
programmer, then it might be acceptable for these modifications to take 
up to a few seconds.

> 6) Object visibility: The topology of an object, at run-time, defines
> the visibility of objects other than those referenced by its own
> slots (dynamic scoping of objects).  The name-binding process is
> equivalent to a search of named slots, starting at the object in
> question, followed by objects referred to by its slots, etc (somehow
> avoiding loops).

You don't want to search all slots, just parents or some equivalent 
notion. Searches through "normal" slots can happen manually, as you 
explained below.

I would just like to point out that there are other links in the object 
topology that we normally don't think about: the literals inside the 
object's code. I find myself appreciating more and more their 
importance.

> This seems to roughly describe an object-oriented environment capable
> of supporting a decent language.  Now the details of interpretation I
> am not solid on right now, but there are a few ways of doing it:
>
> - Find the target object by name - search proceeds as in 6) above.

This would be an implicit self send.

> - Execute its code, returing the target reference.
> - Find the 'message' withing the dynamic scope of the target object.
> If present, evaluate it with whatever parameters.

This would be a normal send.

> Sending a 'no message' message returns the value (equivalent to the
> execution of a method, sending 'value' to a block or fetching a data
> slot).  Note that an object can be referred to by more than one name
> if it's bound to more than one slot.

Ok, except for assignment your "story" seems to work as an explanation 
for Self's syntax and semantics.

> For example, let's say we have an object foo with slots named A B and
> C.  We can assign an integer 4 to A; a method [A * 2] to B; and a
> closure myClosure to C.  Now, there is no difference between blocks
> and method, eh?  The code is completely decoupled from any bindings
> until runtime.

It seems to work with your examples, but things would be more 
interesting if you had a method with arguments and/or local slots in B.

> This arrangement has several benefits over the smalltalk/self model:
> you can totally redirect objects to proxies, or do anything at all at
> the point of lookup and closures are in fact real objects.
>
> 	bar.  (returns the result of evaluating an object at a slot
> name bar in self or above).
> 	bar increment. (returns the result of evaluation of an object
> at the slot named 'increment' found at or above an object at the slot
> named 'bar' in self or above).
> 	bar := 4 (send := 4 to the object at a slot named 'bar' in
> self or above)...

If you are trying to do assignment, it won't work this way. By the time 
object 'bar' gets the ':= 4' message, you no longer have a reference to 
the object with the 'bar' slot, and that is what you want to change, I 
think.

> Sorry about the rambling, but I've been thinking about this for too
> long the wrong way, and the recent brush with self is beginning to
> clear my head (but it's not quite clear yet...)

If it was easy, someone would have done it already and we wouldn't have 
things like C# as examples of great advances in language design. I put 
some ideas I have been working on here:

   http://www.merlintec.com:8080/software/

I probably won't be doing the object format or bytecodes as described 
there. These are just some thought experiments.

-- Jecel



More information about the Self-interest mailing list