how to write function that returns function

Bengt Richter bokr at oz.net
Fri May 17 22:09:12 EDT 2002


On 17 May 2002 01:01:17 GMT, bokr at oz.net (Bengt Richter) wrote:

>On 16 May 2002 23:52:47 GMT, bokr at oz.net (Bengt Richter) wrote:
>
>>On 15 May 2002 16:04:05 -0700, spam at bugbear.com (Paul Graham) wrote:
>>
>>>> You can't directly translate that.  Access to variable of enclosing
>>>> scopes is read only (except in the case of global statements, but that
>>>> doesn't help here).
>>>
>>>It looks as if the closest thing would be something like this,
>>>which a Python expert sent me:
>>>
>>>def foo(n):
>>>  s = [n]
>>>  def bar(i):
>>>    s[0] += i
>>>    return s[0]
>>>  return bar
>>>
>>>Although you can't modify variables from outer scopes, you can
>>>modify *parts* of them (which to me seems like the same thing...)
>>>
>>>The reason this problem seems kind of artificial is that I don't
>>>need to solve this actual problem.  I heard that recent Python
>>>versions had added more support for lexical closures, and was 
>>>curious how well Python works for the type of programming in 
>>>Structure and Interpretation of Computer Programs; this is kind 
>>>of a hello_world of that genre.  (It's not a homework problem, 
>>>I swear.)
>>>
>>>Incidentally, here is Perl 5 code someone sent me for this case:
>>>
>>>sub foo {
>>>  my ($n) = @_;
>>>  return sub {return $n += $_[0]}}
>>>
>><flame shields up>
>> >>> foo = lambda y:([x for x in [[y]]], (lambda: (x.append(x.pop()+1),x[0])[1]))[1]
>> >>> f=foo(20)
>> >>> f()
>> 21
>> >>> f()
>> 22
>> >>> f=foo(-4)
>> >>> [f() for x in 'x'*7]
>> [-3, -2, -1, 0, 1, 2, 3]
>></flame shields up>
>>
>>;-)
>>
>>
>Since [].append returns None, we could use short cut eval rules to prog a tiny bit more clearly:
>
> >>> foo = lambda y:[[x for x in [[y]]], lambda:x.append(x.pop()+1) or x[0]][1]
> >>> f=foo(4)
> >>> [f() for x in xrange(5)]
> [5, 6, 7, 8, 9]
>
>Better yet:
>
> >>> foo = lambda y:[lambda:x.append(x.pop()+1) or x[0] for x in [[y]]][0]
> >>> f=foo(4)
> >>> [f() for x in '.......']
> [5, 6, 7, 8, 9, 10, 11]
>
Boo! I misread an 'i' as a '1' -- to increment by a current arg (not 1) it should be

 >>> foo = lambda y:[lambda i:x.append(x.pop()+i) or x[0] for x in [[y]]][0]
 >>> f=foo(0)
 >>> f(0)
 0
 >>> [f(x) for x in xrange(10)]
 [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
 >>> f=foo(100)
 >>> [f(x) for x in xrange(10)]
 [100, 101, 103, 106, 110, 115, 121, 128, 136, 145]
 >>> [f(1) for x in xrange(10)]
 [146, 147, 148, 149, 150, 151, 152, 153, 154, 155]

Regards,
Bengt Richter



More information about the Python-list mailing list