lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

Dr. Rich Artym wrote:

[some initial context here]

I wasn't using any esoteric meaning of "ordinary".  We were talking about
closures as one very special (or at least specially named) kind of function,
so I used "ordinary function" simply to mean anything that isn't a closure.

After all, the word "closure" must mean something, otherwise why bother
using it?  The plain unadorned word "function" would do just fine, if one
is not referring to a closure.  So, let's assume that a "closure" is the
special kind of function that 30+ years of literature has called a closure.

And what exactly is that?

Well, I guess Guy Steele and Gerald Sussman really ought to know, as the
authors of Scheme and of a ton of academic papers on related subjects:

*** ==>

"Closure - a closure is a function that captures the lexical environment
in which it was created."

I'm just quoting the above as context for this:

That's right, captures the environment, ie. a set of {name, value} tuples,
and not a set of {name, address-of-cell} tuples.  Big difference! :-)

Quoting section 3.1, "Variables and regions" of R5RS
( , all hail offline mode)

An identifier may name a type of syntax, or it may name a location where a value can be stored. An identifier that names a type of syntax is called a _syntactic keyword_ and is said to be _bound_ to that syntax. An identifier that names a location is called a _variable_ and is said to be _bound_ to that location. The set of all visible bindings in effect at some point in a program is known as the _environment_ in effect at that point. The value stored in the location to which a variable is bound is called the variable's value. By abuse of terminology, the variable is sometimes said to name the value or to be bound to the value. This is not quite accurate, but confusion rarely results from this practice.

We now witness this rare confusion.

The term "closure" is not used in R5RS, so that document itself isn't going to be a good way to settle an argument over the term. However, Scheme clearly does have mutable state attached to procedures. In section 6.1, Equivalence predicates, :

The eqv? procedure returns #f if: [...]

o obj1 and obj2 are procedures that would behave differently (return different value(s) or have different side effects) for some arguments.


The next set of examples shows the use of eqv? with procedures that have local state. Gen-counter must return a distinct procedure every time, since each procedure has its own internal counter. Gen-loser, however, returns equivalent procedures each time, since the local state does not affect the value or side effects of the procedures.

(define gen-counter
  (lambda ()
    (let ((n 0))
      (lambda () (set! n (+ n 1)) n))))
(let ((g (gen-counter)))
  (eqv? g g))                   ===>  #t
(eqv? (gen-counter) (gen-counter))
                                ===>  #f
(define gen-loser
  (lambda ()
    (let ((n 0))
      (lambda () (set! n (+ n 1)) 27))))
(let ((g (gen-loser)))
  (eqv? g g))                   ===>  #t
(eqv? (gen-loser) (gen-loser))
                                ===>  unspecified

At this point you have a choice:

1) You can deny that Scheme has closures. It's a lot easier to ignore you in this case, given the web and literature are littered with statements like "Scheme was the first programming language to have fully general, lexically scoped closures."

2) You can find a clearer way to talk about your concept. However, you won't be able to use the emotional charge of "your language needs real closures" to piggyback your argument on.

I think you'll have to attack the R5RS messenger now.

OK, now that I'm done flaming, I have to admit a fascination with the idea of a pure functional scripting language that integrates easily with C code, and is easy to learn.