how to write function that returns function

Bengt Richter bokr at oz.net
Thu May 16 21:01:17 EDT 2002


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]

Regards,
Bengt Richter



More information about the Python-list mailing list