# full closures

Luigi Ballabio ballabio at mac.com
Thu Feb 28 11:02:12 CET 2002

```At 03:47 PM 2/27/02 -0800, Andrae Muys wrote:
> > I don't understand closures, but I might try something like:
> >
> > class Counter:
> >     def __init__(self):
> >         self.count = 0
> >     def __int__(self):
> >         self.count += 1
> >         return self.count
> >
> > counter = Counter()
> > print "the current count is %d" % counter
> >
>
>That works, as does using a generator:
>
>def Counter():
>     counter = 0
>     while 1:
>         print "the current count is %d % counter
>         counter += 1
>         yield counter - 1   # might as well return it :)

Hi all,
the usual Scheme closure thing, twisted and perverted to have it
work in Python but probably very un-Pythonic because of that, would look like:

>>> def counter(x=0):
...     l = [x-1]
...     def f(l):
...         l[0] += 1
...         return l[0]
...     return lambda: f(l)
...
>>> c1 = counter()
>>> c2 = counter(5)
>>> c1()
0
>>> c1()
1
>>> c1()
2
>>> c2()
5
>>> c2()
6

Note: the above only works in Python 2.2 (by default) or Python 2.1 (by
importing nested_scope from __future__)

Much of the awkwardness comes from having to store the counter in a list to
have pass-by-reference to f, and from having to define a separate f because
lambda is limited to a single expression. In Scheme, which has different
semantics, this trick is done much more tersely as

(define (counter x)
(let ((y (- x 1)))
(lambda () (set! y (+ y 1)) y)))

which in non-working pseudo-Python syntax for the parens-challenged would be:

def counter(x):
y = x-1
return lambda: y += 1; y

but one can't have everything. It wouldn't be Python if it had Scheme
semantics...

Bye,
Luigi

```