(eval), space-time, and the interpreter
Posted August 29, 2013on:
I remember reading about Einstein. A source of his genius was how he re-evaluated criteria.
It follows that if everybody looks at the same criteria, and they look at it in the same way, and they all think the same way, then people will reach the same conclusions. And because being different in this world can be painful, most people are not only in incapable of thinking differently, they aspire not to. Einstein looked at criteria differently and found something he liked.
He decided that the speed of light was a constant. That’s it. Many things follow from that one decision. Everybody else looked at the criteria of light and saw the same thing. The conventional wisdom saw nothing new where light was concerned. In his conflict with (eval), I think Alan Kay did something similar. He took something axiomatic, unpacked new criteria, and solved the problem he faced.
Appendix II of the article The Early History Of Smalltalk describes in detail how Kay created the interpreter for Smalltalk-72. Whatever people might say about the origin of Smalltalk, those four pages demonstrate it was hugely influenced by Lisp. Colin Putney once told me that many languages are the combination of two others. “C was invented because Assembly wasn’t enough like Fortran. Smalltalk was invented because Simula wasn’t enough like Lisp”. In the Smalltalk-72 era, Kay had glommed onto Simula. But how could it be synthesized with Lisp?
The battle to be waged was against (eval). Page 92 of Land Of Lisp has:
(defparameter *foo* ‘(+ 1 2))
The problem was that he couldn’t just use eval. As I understand it, the half page of syntax he had (as a part of a bet) left him almost without resources. He just couldn’t add eval willy-nilly. This problem led him to re-evaluate what the criteria of eval were and find a solution. He had two tools at his disposal: time, and, space.
Of course he didn’t say it that way. He said: “When I set out to win the bet, I realized that many of the details that have to be stated explicitly in McCarthy’s elegant scheme can be finessed.”
I like that. Finessed. To me that means he realized he could push the details out to the context and away from the syntax. Instead of locating all the information required in the syntax, many of the details would be ambient. They’d be around. He’d change space by changing the scope. And he’d change time by pushing the processing to late, late, late in the cycle. Dynamic binding is a choice about time and nothing else. First class objects are objects that exist at runtime. They have to be fully formed at runtime. If they were processed earlier, then they wouldn’t have to be.
He said he needed: “a protected way to access and change the relationships of the static and dynamic environment”. No problem. We will change space by confining the scope to that inside an object. Put the processing inside an object, a context object, and then you have complete control over what happens. “I extend(ed) the eval by distributing it”
If you evaluate the (eval foo) as above, then it will happen. Period. No buts. A message in Smalltalk is the location of a letter and not the actual letter. It’s a request for something to happen. And before it happens there are options: the object can ignore it, throw an exception, delegate, or do anything it likes with the request.
Appendix II also talks about the process counter (PC) in both objects and how they have to be synchronized. “Delayed receipt requires the PC counter of the receiver and the sender to be manipulated at the same time.” I’m not quite under that yet. As there is a PC counter in every context object, it shouldn’t take too long.
Interestingly, Matz didn’t have this same kind of resistance when adding eval to Ruby. Avi Bryant says that it can be used for doing Lisp-like programming in the Ruby language:
Since I often see the programming language world (at least, the small enlightened part of it) as being divided into the LISP camp and the Smalltalk camp, it's nice to see something like Ruby strike a decent balance between the two. My particular style of writing Ruby is an interesting example of this: Ruby has the peculiarity that code inside a class definition, but outside a method definition, is evaluated in the context of the class object. In other words, this code class Foo def some_method(x) x * 2 end print self end will print "Foo". This means that it is possible to write class methods that use eval to act more or less like macros, but macros that can be overridden by subclasses, etc.
Sometimes what looks whole and incontestable is made up of smaller parts. Sometimes there are new criteria waiting to be found. Like muons.