how to write function that returns function

Michael Hudson mwh at python.net
Thu May 16 05:07:06 EDT 2002


spam at bugbear.com (Paul Graham) writes:

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

Well yeah, that's what I meant by "can't directly translate"...

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

Really?  I think there's quite a difference.

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

Ah, the real question!  The answer: not well.

> this is kind of a hello_world of that genre

Well, I just swiped this from the online version of SICP:

(define (make-withdraw balance)
  (lambda (amount)
    (if (>= balance amount)
        (begin (set! balance (- balance amount))
               balance)
        "Insufficient funds")))

(define W1 (make-withdraw 100))
(define W2 (make-withdraw 100))
(W1 50)
50
(W2 70)
30
(W2 40)
"Insufficient funds"
(W1 40)
10

I don't suppose you need telling that in Python you do this like so:

class Balance:
    def __init__(self, balance):
        self.balance = balance
    def withdraw(self, amount):
        if amount <= self.balance:
            self.balance -= amount
            return self.balance
        else:
            return "Insufficient funds"

>>> W1 = Balance(100)
>>> W2 = Balance(100)
>>> W1.withdraw(50)
50
>>> W2.withdraw(70)
30
>>> W2.withdraw(40)
'Insufficient funds'
>>> W1.withdraw(40)
10

?  (Ignoring the fact that Python has exceptions...)

> (It's not a homework problem, I swear.)

I didn't think someone called Paul Graham who signs himself pg was
still doing homework...

> Incidentally, here is Perl 5 code someone sent me for this case:
> 
> sub foo {
>   my ($n) = @_;
>   return sub {return $n += $_[0]}}

Yuck <wink>.

Cheers,
M.

-- 
  This makes it possible to pass complex object hierarchies to
  a C coder who thinks computer science has made no worthwhile
  advancements since the invention of the pointer.
                                       -- Gordon McMillan, 30 Jul 1998



More information about the Python-list mailing list