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

Re: Closures



On Fri, Aug 10, 2001 at 09:30:01PM -0400, Samuele Pedroni wrote:
> Jeff Dalton <jeff@aiai.ed.ac.uk> wrote in message
> 200108091600.MAA21550@life.ai.mit.edu...
> > > No, not in Python (lexically surrounding scopes are accessible but
> > > immutable for some reason). This is partly because of Python's odd
> > > mutation-inducing binding dogma, but a real annoyance nonetheless.
> >
> > I suspect the reason's the same as in Java (where you can do the Java
> > equiv of closing over variables only if they're "final") - there's an
> > easy implementation if you copy bindings instead of sharing them, and
> > you can hide the semantic difference by forbidding assignment.
> >
> No we share bindings (in Python) and yes the reason is the dogma <wink>.
> OTOH it is also related at the just one way philosophy: if you really
> need that you can achieve the same with a first-class class with callable
> instances ...

Urgh.  So Python's closures are still broken:

  >>> def counter():
  ...     n = 0
  ...     def increment_and_return():
  ...         n = n + 1
  ...         return n
  ...     return increment_and_return
  ... 
  >>> c=counter()
  >>> c()
  Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    File "<stdin>", line 4, in increment_and_return
  UnboundLocalError: local variable 'n' referenced before assignment

Because I assign to 'n' in 'increment_and_return', Python treats it as a
new variable distinct from 'n' in the enclosing scope.

Perl, on the other, gets the semantics correct but uses an awful syntax.
The program:

  sub counter () {
      my $n = 0;
      sub { $n = $n + 1; $n }
  }

  my $c = counter();
  print &$c(), "\n";
  print &$c(), "\n";

...has the output:

  1
  2

Ruby claims to have true closures, but I can't find anything about them in
the manual under that name.  There's this whole block and iterator thing,
but I can't figure out how to write standalone closures.

Dylan, of course, has both nice semantics *and* a reasonably non-cryptic
syntax.

  define function counter ()
    let n = 0;
    method ()
      n := n + 1;
      n;
    end;
  end;

Cheers,
Eric


Follow-Ups: References: