how to write function that returns function
Bengt Richter
bokr at oz.net
Fri May 17 23:01:28 EDT 2002
On 17 May 2002 15:28:06 -0700, spam at bugbear.com (Paul Graham) wrote:
>Thanks to several people who have sent me Python
>"translations" for the following:
>
>Scheme: (define (foo x)
> (lambda (y) (set! x (+ x y))))
>
Ugly and not recommended, but as close as I've yet come:
>>> def foo(x): return [lambda y:z.append(z.pop()+y) or z[0] for z in [[x]]][0]
...
It seems to work (unlike my previous misreading of incrementing by 1 instead of i
in another example).
>>> f = foo(0)
>>> f(0)
0
>>> [f(x) for x in xrange(10)]
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
>>> [f(1) for x in xrange(10)]
[46, 47, 48, 49, 50, 51, 52, 53, 54, 55]
>>> [f(100) for x in xrange(10)]
[155, 255, 355, 455, 555, 655, 755, 855, 955, 1055]
>Perl: sub foo {
> my ($n) = @_;
> sub {$n += shift}
> }
>
>Here is a summary of the answers I got. This is
>the closest thing to a direct translation:
>
>def foo(n):
> s = [n]
> def bar(i):
> s[0] += i
> return s[0]
> return bar
>
>but it is considered ugly, and the canonical way to
>do this seems to be by defining a class:
>
>class foo:
> def __init__(self, n):
> self.n = n
>
> def __call__(self, i):
> self.n += i
> return self.n
>
Yes, it's much clearer. But I just thought of the following,
which seems to work, and seems to me also pretty clear:
>>> def foo(n):
... def bar(i):
... bar.s += i
... return bar.s
... bar.s = n
... return bar
...
>>> f=foo(4)
>>> f(3)
7
>>> f(10)
17
The function bar is accessible via its own closure and thereby the attribute s.
So the attribute namespace seems to work like an assignable-within closure ;-)
BTW, is a function's appearing in its own closure a problem for the gc?
Regards,
Bengt Richter
More information about the Python-list
mailing list