[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.
More information about the Self-interest