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

Re: Closures



Jeff Dalton wrote:

> 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()

It closes but still you can't assign:

def make_counter_with_incr(inc):
  class ctr:
    def __init__(self):
       self.n = 0
    def __call__(self):
       self.n = self.n + inc
       return self.n
   return ctr

c=make_counter_with_incr(4)
print c()  # 4
print c()  # 8


>
> 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.

Here the rationale for Python, mostly a GvR (aka Python BDFL) point:


>     There are technical issues that make it difficult to support
>     rebinding of names in enclosing scopes, but the primary reason
>     that it is not allowed in the current proposal is that Guido is
>     opposed to it.  His motivation: it is difficult to support,
>     because it would require a new mechanism that would allow the
>     programmer to specify that an assignment in a block is supposed to
>     rebind the name in an enclosing block; presumably a keyword or
>     special syntax (x := 3) would make this possible.  Given that this
>     would encourage the use of local variables to hold state that is
>     better stored in a class instance, it's not worth adding new
>     syntax to make this possible (in Guido's opinion).
>
>     The proposed rules allow programmers to achieve the effect of
>     rebinding, albeit awkwardly.  The name that will be effectively
>     rebound by enclosed functions is bound to a container object.  In
>     place of assignment, the program uses modification of the
>     container to achieve the desired effect:
>
>     def bank_account(initial_balance):
>         balance = [initial_balance]
>         def deposit(amount):
>             balance[0] = balance[0] + amount
>             return balance
>         def withdraw(amount):
>             balance[0] = balance[0] - amount
>             return balance
>         return deposit, withdraw
>
>     Support for rebinding in nested scopes would make this code
>     clearer.  A class that defines deposit() and withdraw() methods
>     and the balance as an instance variable would be clearer still.
>     Since classes seem to achieve the same effect in a more
>     straightforward manner, they are preferred.
>
>

A special syntax was needed and the effort was deemed counterproductive.


(PEP 227,  http://python.sourceforge.net/peps/pep-0227.html  )

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

Yes

That's all folks.

PS: GvR is known to have said something along the line of: the mind of the
average Python programmer is simpler than that of average Lisp programmer.
I think both groups get an appropriate set of tools.

What I miss sometimes in Python are (dylan/Lisp like) macros, but that would
be a major exercise in language design and would clash with the
everything-happens-cleanly-at-runtime semantics of Python. GvR probably will
never let such a beast sneak in the language.