Sorrow, OOPAL and Lispy Forth
Last updated at 3:52 pm UTC on 14 January 2006
15 February. 2004, Avi Bryant I've just put up a package called "Sorrow" on SqueakMap, which is an extremely simple compiler for a language inspired by the "functional Forth": Joy. http://www.latrobe.edu.au/philosophy/phimvt/joy/j01tut.html It may be clear that this maps pretty directly to Squeak bytecode, which is why the compiler is so trivial (around 30 lines).
Stephanne Ducasse: Have you looked at F-script and the OOPAL model presented at OOPSLA last year by Philippe Mougin? Because I still would like to see if this can be introduced in Squeak with/without modifying the VM. I just have to find a good student and Philippe is willing to help. I browsed the objective-C code and this is not really complex. http://www.iam.unibe.ch/~scg/Archive/Papers/Moug03aOOPALOOPSLA.pdf
Avi Bryant: Yes, I've looked at F-script. I don't see that we would need any VM modifications to support it, just some compiler extensions. We just define, e.g.
x @foo: y
to be syntactic sugar for
x collect: [:each | ea foo: y]
x foo:@ y
to be syntactic sugar for
y collect: [:each | x foo: ea].
x @foo:@ y then needs to be
x collect: [:eachX | y collect: [:eachY | eachX foo: eachY]]
and so on. I haven't thought yet about what would happen with @@, but I expect it should still basically be a macro expansion to sends of #collect:. We could also use DNU to support his "implicit message patterns", which would interpret "x foo: y" as "x @foo:@ y" if they were both Arrays, but personally I would rather do without that.
David Farber Doesn't this fundamentally break Smalltalk's simple Object-Message syntax? In the case of [each x add: y], each is not an object and x is not a message. How about [x each add: y], etc.?
Aaron J Reichow: After playing with F-Script myself a while back, I implemented something similar in Squeak. But instead of "x @foo: y", I just implemented a method- Collection>>#@ (which broke the method of the same name to create an array of points) that allowed you to do it this way:
x @ foo: y
Not much different, just one space. And it didn't require any modifications to the parser, or overwriting DNU at the level of Object.
QuestionDavid Farber I'm afraid I don't follow. What did your implementation of Collection>>#@ look like? #@ is just a symbol–so why did there have to be a space between @ and foo:? Did this work for x foo: @y? Or x @foo: @y?
AnswerAaron J Reichow: x foo: @y didn't work; nor does x @foo: @y- only x @foo: y, although it had to be written as x @ foo: y. The @ method on collection returned another object, whose DNU was overridden, and when called, would just do a collect: [ :a | a foo ] on the collection, x.
Collection>>@ then. Old habit of writing Class>>#methodName.
Sorrow, OOPAL and Lispy Forth Combining this two ideas gives:
x each add: y
which I would like a lot.
Aaron, could you rename @ to each (thus also removing compatibility issues with Collection > @} and send your code?
DucasseHi David, I'm sure that I'm replying to your questions [about breaking the Smalltalk’s simple object: message syntax] but I think that this is something I learned while playing with the idea of OOPAL. The key idea behind OOPAL is that this is a generalization of message passing. You will send a message to an array or collection and the message will be sent to all the elements of the collection.
Avi I forwarded your question to Philippe because he is the expert and we always thought that we wanted speed hence were thinking about modifying the VM because array of integer, booleans and treated in a special way.
[Regarding the Arron’s idea] Sure you can do that but Philippe was looking at having something optimized. Read the OOPSLA paper and you will understand. The fact that you generate a lot of collection of boolean or only number can make that really efficient.
Philippe Mougin As Avi said, OOPAL's explicit message patterns can be handled at the compiler level (and maybe even directly at run-time using Marcel Weiher's HOM-like tricks). We might need something a little bit more sophisticated than the expansion to collect: envisioned in Avi's message, though (for instance, the example for handling x@ foo:@ y by transforming it to x collect: [:eaX | y collect: [:eaY | eaX foo: eaY]] is not correct: what we end up with is an outer product, not an element-wise application of the foo: method). Explicit message patterns can be handled by the compiler (or compiler + some run-time support) with very good performances.
It is useful to handle implicit message patterns in the message sending routine itself. As far as performance is concerned, an important goal when implementing OOPAL's message patterns is to avoid any performance impact for the common, single message sending situation. In general, implementing support for implicit message pattern in the message sending routine allows you to easily achieve this "zero cost" goal.
However, the suggestion of implementing OOPAL's implicit message patterns trough DNU is interesting because, performance wise, I think it would also allows for a "zero cost in the classic case" implementation. But I'm not sure implementing implicit message pattern using DNU is possible (it might be possible, but, at first glance, it is not that obvious for me).
Syntax for message patterns: F-Script use the @ symbol for denoting message patterns, but this is not really adapted for Smalltalk because in Smalltalk @ can be used as selector (in F-Script @ can't be used as a selector). Using @ in Smalltalk would introduce an ambiguity. For instance in the expression x @ y, are we invoking the method @ on x or are we describing a message pattern. Adapting OOPAL to Squeak would probably require to replace the @ based syntax by something else (this would have the added benefit of making Andreas happy ;-)
Finally, note that message patterns are only half of the story. They become really, really powerful when you mix them with APL-like operations like compression etc. For instance, here is an example taken from the OOPAL paper http://www.fscript.org/download/OOPAL.pdf. You have a collection P of objects representing pilots and you want to get the name of those whose age is greater than 50. In Smalltalk you do:
(P select:[:aPilot| aPilot age > 50]) collect:[:aPilot| aPilot name].
In Smalltalk + OOPAL you do:
P name at: P age > 50
OOPAL's message patterns and APL-like array operations really go hand in hand.