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

Re: Closures



> > That's not a "closure", it's an "object".  They can be used for many
> > of the same things, but they are different.

While that's true (though of course closures are a kind of object),
we can see a closer analogy in some cases than in others.  For
instance, it could be argued that when you instantiate an anonymous
inner class in Java you don't strictly speaking get a closure;
nonetheless it "closes over" local variables.

The Python "idiomatic way to get the same" below does not seem to
close over local variables at all.

> > > There is simply another idiomatic way to get the same:
> > >
> > > class counter:
> > >   def __init__(self):
> > >      self.n = 0
> > >   def __call__(self):
> > >      self.n = self.n + 1
> > >      return self.n
> > >
> > > c=counter()
> > > print c()
> > > print c()

If so, this stretches the "just one way philosophy" more than I
would like, because it's not clear where you would then draw the
line.  For example, how do I get the equivalent of two (or more)
closures over the same bindings?  I'm sure there's some way to
implement something that behaves in much the same way, but the
same might be said of, say, floating point numbers, because you
could implement a collection of functions that operate on "floats"
represented by pairs of integers, or something like that.


I've noticed that the designers (and probably users) of many languages
don't seem to care about having closures with the "shared binding"
assignment semantics and hence are willing to put up with assignment
behaving differently when it "crosses" the lexical boundary of
the inner procedure, function, or whatever.  They seem to be quite
happy with some kind of "approximate closure" that has some other
assignment semantics and is typically easier to implement.

(Another example is Pop-11 and related languages, where they use
"frozen formals", a kind of currying, again without shared bindings.)

This is in contrast with Lisp.  In the various kinds of Lisp, there
were a number of experiments different kinds of "approximate
closures", but there was often an effort to get the "shared binding"
semantics even when other things were rather messy.  (For example, you
might have to explicitly list the variables to close over and declare
them all to be dynamically scoped.)  No one approach achieved general
acceptance until proper lexical closures came along.

My guess is that the Dylan designers (you see, I did eventually get
around to Dylan) never seriously considered anything else.

The interesting question is why:  why have Dylan and modern Lisps
gone this way when virtually no one else has?  Why were Lisp and Dylan
not satisfied with some kind of "approximate closure" when so many
others were?  Java came close but didn't take the final step of supporting
assignment.  In functional languages, the issue doesn't arise (no
assignment); and in ML they avoid it by using explicit ref objects.

(By the way, does Perl have lexical scoping?)

-- Jeff


Follow-Ups: