words of power from the ancient world
By John.Rose-Oracle on Mar 29, 2008
These terms name basic ideas and patterns that we, as programmers, do not know how to live without. We make up new terms for the old concepts, and endow the old terms with new meanings, but there seems to be a resonance among the old terms and meanings that was established early on by general consensus, as more than a simple convention.
I am thinking particularly of the words “continuation” and “closure”. They sound vaguely mathematical but they are not. It is hard to find a clean definition for them, even today. It seems to me that luminaries like Hoare, Landin, Strachey, Reynolds, and various MIT AI Lab researchers, busy trying to bridge the gaps between computer behavior and programmer reasoning, had to invent terms on the fly.
If a term had enough raw metaphorical power, it could take on some life. Some terms did not thrive: Continuations once kept company with program-closures and dumps. It did not matter in the long run whether a term was defined rigorously for the purpose of a paper, or whether (in a hallway conversation?) it was defined implicitly by usage. As Peter Landin says, “Such a borrowing from ordinary language can certainly bear several meanings.”
Meanwhile, in other hallways and papers, as the same basic idea was repeatedly rediscovered and reused, a good term could be reused, and could accumulate more useful definitions. John Reynolds’ paper “The Discoveries of Continuations’, reprised I think in a 2004 talk, tells more of this story.
With closures, there seems to have been a point at which someone said, during a discussion of frustrating scoping bugs in Lisp, “you cannot have just program or just data, you must have a little record that combines the two; it is a ‘closure’ of the two”... and that was enough. The metaphor is that free variables are inconveniently open to the surprising effects of dynamic scoping, and must be closed in order to use safely. Joel Moses (cited in the previous link) tells how the AI Lab learned about non-dynamic scoping:
A useful metaphor for the difference between FUNCTION and QUOTE in LISP is to think of QUOTE as a porous or an open covering of the function since free variables escape to the current environment. FUNCTION acts as a closed or nonporous covering (hence the term "closure" used by Landin). Thus we talk of "open" Lambda expressions (functions in LISP are usually Lambda expressions) and "closed" Lambda expressions.
The paper goes on to record standard excuses we language implementors always give to our users, when we hand them warty, bug-bait semantics. They are, you wouldn’t know how to use it, and it’s too expensive anyway:
It has been our experience that most LISP programmers rarely return closed Lambda expressions, and hence rarely encounter the full environment problem. There does not currently appear to be any way of solving the complete environment problem efficiently without losing efficiency whenever one accesses or modifies free variables.
(We language users should always be ready to reply, we refrain from using it only because your implementation of it stinks, and go and figure out how to do it efficiently, please.)
Even from the depths of time in 1970, Moses harkens back even further:
Peter Landin once said that most papers in Computer Science describe how their author learned what someone else already knew. This paper is no exception to that rule. My interest in the [lexical scoping] problem began while Landin, who had a deep understanding of the problem, visited MIT during 1966-67. I then realized the correspondence between [Lisp closures] and ISWIM's Lambda Closures.That final reference nicely closes the temporal loop on all of us: P.J. Landin, "The Next 700 Programming Languages", CACM, March 1966. That, of course, is Landin’s paper more or less accurately describing the (repetitive) course of programming language design through the present. In particular, we are still rediscovering closures, and the simple lexical scoping rules they were invented to support.
And by the way, we (that is, we language implementors) are still mangling this stuff. If your favorite language’s soi-disant closures still keep variables subject to dynamic scoping or refuse to compile an construct that reaches out to an enclosing scope, then that language still suffers from the Lisp 1.5 bugs that closures were introduced to fix. (Especially if it supplies some dynamically determined substitute for the unavailable static meaning, as with Smalltalk out-of-scope returns. Simple refusal is better, in my book, than bait-and-switch. That is why your uplevel references in Java are final.) It is true that our poetic terms of art collect new meanings as we go along, and moreover it is best if the new meanings can illuminate the old meanings, rather then obscure them by contradiction. So closures which don’t really close all the way, don’t deserve to be called closures. Call them semi-closures, or inner classes with closure-like features.
Finally, and for what it is worth, here’s my vote that somebody who was there will give a talk or paper of “The Discoveries of Closures’.