What is a closure?
“In computer science, a closure is a function that is evaluated in an environment containing one or more bound variables. When called, the function can access these variables.”I will add a few belated comments to the original article in red.
What do you understand is meant by the term, “closure”? In a discussion in the comp.lang.misc newsgroup almost everyone seemed to take it as meaning a partially instantiated function. BTW the term “partially instantiated function” is used by Jeffrey D. Ullman, author of “Elements of ML Programming”. It strikes me as a much more precise term; however it doesn’t seem to have caught on – a google search turns up few references.
Partially instantiated function is close to the comp.lang.misc usage, though not necessarily to the wikipedia definition.
Likewise, using the term “closure” for a partially instantiated function seems a bit off. In the discussion I wrote:
“Let me quote from “The anatomy of Programming Languages” by Fischer and Grodzinsky:One can argue to the contrary that there is no good term for the thing being enclosed (“open expression” apparently is not a good term) and “closure” reflects the meaning. Be all of that as it may, usage is the master. A closure is what the users of the word say it is.Closure is an operation that can be applied to an expression. We close an expression by binding each of its free variables to the value of another expression. A closure creates a function, which is returned as the result of the closure process.Now this is a definition that makes sense (at least it does to mathematicians). My point here is that a closure is what you get after you bind the free variables and have a closed expression.”
The fundamental problem with the term, closure, is that different users say different things. In fact, quite often the same user will say different things in different contexts. A closure can be the expression/function/block that is operated on to produce an executable expression/function/block, the operation of closure itself, or the resulting expression/function/block.
There is, however, another objection that occurs to me, namely that the usage is unduly restrictive. The essence of the matter is that the variables being instantiated must be in the calling sequence list and must be filled in the list order. [I’m ready to be corrected on this point.]
Let me correct you, Richard. The only things that this business of putting a series of functions in a calling sequence has do with closures are (a) you can implement it using closures, and (b) many people call it using closures. What it actually is is a convenient notation for function composition.For example consider a bit of scheme that Nils Holm contributed:
(define complement (lambda (f) (lambda (x) (not (f x))))) Usage: (number? 123) => #t (complement number?) =>; #<closure> ((complement number?) 123) => #fWhich is quite nice, but suppose we want (not legal scheme)
(complement ??? 123)i.e, we want a closure that will be instantiated by the first argument rather than the second. In the example there is no ambiguity – there is only one argument visible at the outer level. In general in languages like ML there similarly no ambiguity since there is only argument, the list containing the arguments (Currying doesn’t change this.) But this elimination of ambiguity is done at the price of forcing instantiation to occur in sequential order.
In the general situation we could have a function f with n arguments, a1,a2,…,an and desire to form a closure by binding a particular argument or set of particular arguments. Even more generally we might have an expression with blank spots, an expression that can be used in multiple places with different instantiations. For example, in some language we might be able to say something like
foo = (expression %1 + %2) foo1 = (close foo %1 = 2) foo2 = (close foo %2 = 3) with the obvious interpretation and usage: print (eval foo1 3) => 5 // foo1 closes to 3+2 print (eval foo2 2) => 5 // foo2 closes to 2+3Some languages, e.g. Ocaml and Algol 68 Genie, allow this.
This page was created August 1, 2005.