New macro-based syntax conveniences

Brian Rice water at tunes.org
Mon Oct 18 12:00:48 PDT 2004


After some consideration, Lee has put together some macro-methods which 
allow for the conveniences of Smalltalk-80's cascade syntax. Alpha 
images are available in the usual place on the Slate website.

To summarize, Smalltalk-80's cascade syntax allows repeated 
message-sends to the same object, eg "someObj foo; bar; baz: quux; 
yourself" sends #foo, #bar, and #baz: with a quux argument to an 
object, then returns the object itself using the yourself message. This 
is a common idiom in creating and setting up a new object, or 
activating many behaviors in sequence on the same thing (used in a lot 
of UI code - or, well, in general with objects that have many variables 
or are "facade" objects).

In Slate, we did not want to treat the first argument of a message send 
as a special "receiver", and the semi-colon makes a useful binary 
selector, so we dropped cascades. Our solution now is a macro-method 
which takes an expression (well, its result) and a block, and enhances 
the block so that the result of the expression becomes the implicit 
context for statement-level (top-level) message expressions. For 
example:

Slate> (addPrototype: #Something derivedFrom: {Cloneable}) `>> 
[addSlot: #foo. addSlot: #bar].
("Something" traits: ("Something" printName: 'Something'. parent0: 
("Cloneable" ...). traits: ("Traits" ...)). foo: Nil. bar: Nil)

In this expression, a prototype is created and returned by the first 
expression, and the block is evaluated with that object substituted for 
the context, so that the addSlot: calls apply to it directly.

There is an additional possibility that it takes care of by allowing 
the user to specify an input variable to the block, which will also 
allow the code within to refer to the object explicitly. Also, the 
default return value for empty-last-statements is modified to be this 
object instead of Slate's usual Nil. These features eliminate the usual 
need for the #yourself message at the end of a cascade. To see the 
effect this would have on Slate library code, I'll take a collection 
creation method as an example:

c@(Set traits) newSize: n
[| newC |
   newC: c clone.
   newC contents: (c contents newSize: (n max: 1)).
   newC tally: 0.
   newC
].

could become:

c@(Set traits) newSize: n
[c clone `>> [contents: (c contents newSize: (n max: 1)). tally: 0. ]].

So in this new method, an object is made by cloning the argument Set, 
and then the contents and tally are assigned as before, but not needing 
to refer to the object explicitly, and then returning the object (if 
the ending period is left off, it'll return the value of the last 
explicit expression, just as normal blocks). Notice that `>> is 
composable. Also, notice that the message-sends which are not leading a 
statement do not (and cannot) use the object as implicit context. This 
is intentional, as the results of this kind of pervasive change are 
more drastic and would be an entirely different kind of idiom.

(Note: the change in the default return expression for an empty last 
statement is recent and will be reflected in new alpha image uploads. 
Don't evaluate it immediately, as Set is a core collection and this 
will return Nil's, and hang your image.)

The other macro he has introduced allows for the slots of an object to 
appear as local variables in a method, responding both to accessors and 
mutators in the appropriate way (by modifying the object's slots).

So, the following expression names some slots in the first argument 
which should be available as inputs to the second argument, a block. 
This is analogous to having Smalltalk's direct slot reference syntax 
(or Self's, for that matter), or to Lisp's with-slots macro.

Slate> Cloneable clone `>> [addSlot: #x valued: 2. addSlot: #y valued: 
2] `withSlotsDo: [| :x :y | x + y].
4

(Note: this method was renamed just now from `usingSlots: and will be 
reflected in new alpha image uploads.)

--
Brian T. Rice
LOGOS Research and Development
http://tunes.org/~water/




More information about the Slate mailing list