Feature request: subclassing FunctionType [Was: Some language proposals]

Michele Simionato michele.simionato at poste.it
Sun Feb 29 10:37:44 CET 2004

bokr at oz.net (Bengt Richter) wrote in message news:<c1qo74$s9j$0 at>...
> But you can generate multiple closures with separate values
> (which maybe your scheme code really is doing?):
>  >>> def make_separate_adders(n):
>  ...     return [(lambda sepval: lambda x: x + sepval)(i) for i in range(n)]
>  ...
>  >>> add0, add1 = make_separate_adders(2)
>  >>> print add0(0) 0
>  >>> print add1(0)
>  1
> Here the lambda being _executed_ as well as _evaluated_ in the list comprehension provides
> the closure environment for the lambda expression only being _evaluated_ (inside the one
> being executed, to generate code looking for sepval). UIAM ;-)
Hi Bengt! You reduced your contribution to this list in the
last few months, it is nice to see you back :-)

For what concerns the trick you are talking about, it is the workaround
I often use in this situation. Of course, I don't nest the two lambdas
together and I write something more like

def adder(sepval):
    return lambda x : x + sepval

def make_separate_adders(n):
    return [adder(i) for i in range(n)]

which does the right thing and is readable too. But still it is
easy to forget that the helper function is needed and that using
directly the lambda would not work. It is kind of error prone.
Scheme is less error prone since it uses local loop variables and 
automatically generates separate closures:

(define list-of-adders '())

(let loop ((i 0))
  (set! list-of-adders (cons (lambda (x) (+ x i)) list-of-adders))
  (if (= i 1) 'exit (loop (add1 i))))

(define add1 (first list-of-adders))
(define add0 (second list-of-adders))

(print (add0 0)) ;=> 0
(print (add1 0)) ;=> 1

You can get Python behavior if you explicitely use a global variable:

(define list-of-adders '())
(define i 0)

(let loop ()
  (set! list-of-adders (cons (lambda (x) (+ x i)) list-of-adders))
  (if (= i 1) 'exit (begin (set! i (add1 i)) (loop))))

(define add1 (first list-of-adders))
(define add0 (second list-of-adders))

(print (add0 0)) ;=> 1
(print (add1 0)) ;=> 1

So, in a sense, Python and Scheme have the same scope
rules here, but in Scheme you don't see the issue
because you just use a local variable, whereas
Python by default use a global loop variable.

        Michele Simionato

More information about the Python-list mailing list