lewis (03/31/83)
(hope this doesn't get in twice) Now that this group seems to actually have some discussion on it, even one article bemoaning the lack of an implementation, I'm going to jump in. I've recently designed a language, which I call Spadina, that is heavily based upon Smalltalk - primarily 76, since that's what I'm most familiar with. It extends it in a few ways that I thought would be interesting, but is still unstable. In particular, one feature of it is that it uses continuations rather than simple call-return. That it, when a message is sent, one of the parameters of the message is an object that should be sent the result. Normal call-return consists of creating an object that understands a message containing one parameter, and passing it as the continuation. Any method is free to ignore a continuation, and to call another one, for example, or to save a continuation, or anything that you can do with a normal object. The result of this is that it's really easy to generate control structures in Spadina. To do things like while statments with an exit you don't have to pass booleans out of the body; instead you pass the continuation of the loop to the body - it can then call it directly to exit from the loop if it wants. Here are a couple of examples - the first one teaches objects to understand the while message without exits. The ~> token in a message receiver indicates that the continuation is to be bound to the next name. In a message, it indicates the value that is to be used as a continuation, rather than creating one for call return. By explicitly supplying a continuation that is the same one a you are called with, tail recursion is achieved. The token :: means passed by name. object scripts: ` while :: cond do :: body ~> q [ cond -> [ body; self while :: cond do :: body ~> q; ]; ] ' Here's the more complex example. The only different thing about this is that it uses closures, which in Spadina can understand more than one messages. Some receivers enclosed in a { } pair create a closure. A closure can be created to understand messages of the same forms as a class, and so can be considered to be an instance of a class. There are no instance variables, however, as a closure is intended to use the bindings of the environment that it is created in. This example creates a closure that understands the imperative message "exit", and just passes control to the continuation of the while. This closure is passed as a parameter to the body of the loop; see the example below it for usage. object scripts: ` while :: cond doexit : body ~> q [ cond -> body exitis: { exit [ q ~^ : nil; ] }; self while :: cond doexit : body ~> q; ] '; i <- 0; fred while:: i != 10 doexit: { exitis: outer [ j <- 0; fred while:: j != 10 doexit: { exitis: inner [ a(i)(j) = -1 -> outer exit; a(i)(j) = 0 -> inner exit; ] } ] }; This example shows another truth about Spadina - not all the bugs and clumsy parts have been gotten out yet. In the above example fred is useless - just a random object that understands while::doexit:. My favourite examples of how wonderful continuations are the construction of goto's (as a perveted example of the generality of the language), which takes about 7 lines of code, and the construction of monitors, conditions, and fork, without using any parallelism in the implementation, in about 60 lines. The latter example keeps a queue of continuations around for the run queue, and a couple for each monitor. Fork just places a reference to the continuation in the run queue and returns. Some other things that Spadina has are dynamic bindings of variables, multiple "global" environments, different access to traits, and a different handling of "arrays". At any rate, my first implementation is almost done, and I'm willing to send it out to most people free when it is (April-May). I'm interested in comments/ suggestions, and hope this hasn't been too long or boring. author new title: "david lewis"