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

Bengt Richter bokr at oz.net
Sat Feb 28 13:55:32 EST 2004


On 26 Feb 2004 21:58:41 -0800, michele.simionato at poste.it (Michele Simionato) wrote:
[...]
>a real object. On the other hand, I am really bothered by the scoping
>rules. My first post on this mailing list some time ago was caused by
>problems I had with the surprising scope rules. Take for instance
>this example:
>
>def make_adders(n):
>    return [(lambda x: x+i) for i in range(n)]
>
>add0,add1=make_adders(2)
>
>print add0(0) #=> 1
>print add1(0) #=> 1
>
>This does not work as expected, and the solution is an ugly hack
>with default arguments:

I got misled by those near-each-other i's too, but though they both mean use-the-x-binding-in-
a-particular-environment, the use is not at the same time. The code from the lambda
expression evaluation does not look for i until it gets executed at some future time that could be
arbitrarily long after the list comprehension is done with its i-value side effect in the local
namespace of make_adders.

I agree it is easy to make the wrong assumption, with those i's seemingly in the
same expression context, but what should be the expectation? I think the problem is that
lambda x: x+i is a lambda expression, that results in a function, but the i is a name,
not a value in the context of the lambda expression per se. Thus the result is
code that looks for the value of a name someplace, not code that refers to a
specific value. If you want the name lookup to find different values, you must
provide different name bindings, which you don't get in the single closure
reflecting the environment of the list comprehension in make_adders above.

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

[...]

I think having function instances be first-class instances of a first-class function class would
be a unifying move. (First-class class sounds funny) I wonder if we can integrate the creation
of generators and coroutines (and even threads?) nicely in that, in some hierarchy. I'd like to
think about that some, but no time for now. Ciao ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list