[self-interest] Improvements to Self?

Jecel Assumpcao Jr jecel at merlintec.com
Wed Aug 15 00:13:48 UTC 2001


On Monday 13 August 2001 17:16, Ian Woollard wrote:
> All languages need primitives. The point is to get the greatest
> expressibility from the primitives.

Indeed, I was just wondering what your ":" brought us that we didn't 
have with Self's "<-".

> >          ((button font: f) size: 40 at 10) color: bc
> >
> > and so on. Of course, the needed parenthesis ruin it for scripting.
>
> Yes. More like:
>
> myNewButton: button new: Size: 40 at 10 Font: f Color: bc
>
> It makes all the difference in readability.

In Smalltalk there is the cascaded messages syntax:

    myNewButton <- Button new size: 40 at 10; font: f; color: bc

and GNU Smalltalk is already pretty good at scripting applications. But 
prefer to create programs (scripts or not) graphically instead of by 
typing, so I don't worry about syntax as much.

> > Self didn't have lexical scoping until the latest release - Self
> > 4.0 still faked it with inheritance.
>
> That's odd. Why add lexical scoping?

Using new special bytecodes for accessing local variables makes an 
interpreter more practical than with the original self send bytecodes. 
Self 4.1 is the result of several interesting experiments including 
such an interpreter.

There are also new branch bytecodes which the parser could use for 
popular control structures, but I didn't notice this actually being 
done. Neither of these changes make much of difference for a compiler. 
And neither required any source code changes at all, so they are 
transparent to most programmers.

> OK. I clearly don't understand lexical scoping! What's the point of
> it; how can it be better than inheritance?

Lexical scoping is when the text of the program shows you what names 
are visible at a give point in the source:

           sillyExample: arg = ( | temp <- 0 |
                  arg > 7 ifTrue: [ temp: 2 * arg ].
                  temp + myBase
           )

Inside the block both "temp" and "arg" are used, though they are not 
defined locally. But the block is lexically embedded inside a method 
that does define these names, so it is reasonable for a programmer to 
expect that they could be used there.

We use "myBase" which is not defined anywhere in the above example. We 
are supposing that this is defined inside the object that will receive 
this message or in one of its parents. In Self this works due to the 
:self* argument slot which makes the receiver a parent of the execution 
context. In other languages this works because the text of the method 
is defined inside the text that describes the object, so "myBase" is 
available in the outer lexical scope.

If you use lexical scoping exclusively to indicate inheritance, then 
your program must be a text with a very strict nesting structure. This 
is what Beta is like and it does a good job of it. In Self we like to 
have objects floating around the screen pointing to each other without 
one being "inside" the other in any sense. Explicit parent pointers are 
the way to show what names we are importing into the local context. But 
this would be awkward for something as small as the block above, so we 
don't write anything and let Self 4.0 takes care of all the hidden 
parent pointers. Or Self 4.1 take care of accessing lexically enclosing 
contexts at runtime. It doesn't make much of a difference in practice.

> > [private slots in Self 1 and 2]
>
> Not really the same thing. If I inherit off an object I have
> access to the private slots. That's bad.

But sometimes that is exactly what you want to do. So you would need:

  - public slots
  - private inheritable slots
  - totally private slots

Otherwise any public method that called a private one would break when 
invoked by a child object that didn't reimplement the private one.

-- Jecel



More information about the Self-interest mailing list