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

Jecel Assumpcao Jr jecel at merlintec.com
Thu Dec 20 23:57:42 UTC 2001

> Now, the lifespan of a block, as you pointed out, is limited to the
> lexically enclosing method.  As an implementer, I can understand the
> desire to keep activation records on the stack for efficiency, and
> that implies that the record cannot survive the stack frame of the
> method.  However, it does preclude me from passing a block out of a
> method and sticking it into a slot of a more permanent object. 

The quote in my previous message was meant to imply that the main Self 
people are unhappy with the situation you describe above and that this 
is very likely to change in the future.

> That
> seems like a deficiency as I often find myself (in smalltalk) in
> situations where I really wish to replace a method with another one
> after the state of the object changes (instead of a slower
> conditional).  Am I missing something here - is there another
> mechanism in self to replace the contents of a slot with another
> (precompiled or dynamically generated) entity?  I guess you can
> replace the contents of a slot with anything you want, so that would
> be the way to do it.   It just really yanks me that the creation of a
> block and a method is not syntactically identical.

It is very simple to have many slightly different objects in Self, so 
many design patterns that use non-LIFO blocks in Smalltalk can easily 
be implemented with "anonymous objects" in Self. Smalltalk's

   sortBlock := [ :a :b | a age > b age ].
      sortBlock value: arg1 value: arg2
   sortBlock := [ :a :b | a weight > b weight ].

can easily be implemented in Self as

   sortObj: ( | compare: a And: b = ( a age > b age ) | ).
      sortObj compare: arg1 With: arg2
   sortObj: ( | compare: a And: b = ( a weight > b weight ) | ).

It is more awkward in the simple cases, but actually becomes more 
usable than the Smalltalk alternative when you want the parameter 
objects to understand more than one message.

> As for scoping, do I really understand it correctly that a block
> statically binds to objects of the enclosing method at compile time?

No - a clone of the block's value method is bound at run time to a 
clone of the enclosing method. That is a rather different thing from 
saying that the block object is statically bound to the enclosing 
method object at compile time (which is true). See my explanation in 
the previous email about the three different objects needed to 
implement blocks.

> It would be just so much cleaner to bind at run time... Ah...  It
> seems like there are at least two distinct uses of a block:
> partitioning a method (requires lexical access to method slots), the
> other a generic submethod to be passed around (such as a sort block),
> requires dynamic access to run-time method's slots that can be faked
> by passing parameters.  Perhaps these should be treated as different
> animals, or the programer be given the choice of lexical/dynamic
> binding of a block?  Of course, dynamic binding works in both cases
> as the partition-type block is executed within the same method it was
> compiled in...

Not if I understood what you meant by "partition-type block". Consider

    ....  x < 0 ifTrue: [ x: 0 ].

This block is actually executed inside the 'ifTrue:' method in the 
boolean object 'true', not the current method within the current 
receiver ('self'). For dynamic scoping to work we need to have some 
link going from the 'ifTrue:' clone (closure) to the current execution 
context (where 'x' is defined) *and* 'ifTrue:' itself must *not* define 
its own 'x' slot. The first problem is also present in lexical scoping 
(and it less elegantly solved there) but at least we get rid of the 
second problem.

> To clarify my seminonsensical last message, it seems that there is a
> more generic way to implement an oo environment within which self can
> be instantiated, just like smalltalk can be instantiated in self...

That is what I am looking for.

> The object with slots and data/code (data of course is code
> interpreted by some program or hardware...) seems like about as low
> as I would be willing to go.  From there on, it is mostly the
> question of when to bind.  Bind everything at compile time and you
> have Forth.  Bind objects at compile time and messages at runtime,
> and you have Smalltalk.  Bind everything at runtime, and what do you
> have?

I like Forth :-)  You lost me in the part about Smalltalk binding 
objects at compile time.

> You are totally right about my missing out on the assignment issues.
> The big problem here is name binding again - do names bind the slots
> or objects inside those slots?  Is a slot, perhaps, an object capable
> of assignment? I have to think about it some more as I am quickly
> approaching middle age and my mind is not working as well as it did
> (or at least as I remember it doing).

How do you know that you mind doesn't work better now but your memory 
of how it used to be has been damaged? ;-)

You might enjoy a previous thread I started about assignment and 
arguments on this list:


-- Jecel

More information about the Self-interest mailing list