Why functional Python matters

Tim Peters tim.one at comcast.net
Wed Apr 23 23:17:15 EDT 2003


[attribution lost]
>>> But he regrets the inclusion of a crippled lambda, rather than the
>>> inclusion of support for anonymous functions (IIRC).

[Courageous]
>> Anyway, I guess what I'm saying is that I suspect that Guido
>> didn't have any good alternatives.

[Mark Jason Dominus]
> I don't believe that's correct.

In the Python world, you're missing the context:  lambda was in version 1.0
of Python.  They're "crippled" not so much because they didn't support
closures (they do in current Pythons, BTW), but because they're
syntactically limited to a single expression, and Python is not an
expression language (Python statements are not Python expressions, so no
matter how perverse you try to be, you can't write a Python lambda that
contains a Python statement -- what you can do inside a Python lambda is use
a crippled subset of the language).

That said, Guido regrets lambdas anyway <wink>.

> At an early Open Source Conference, perhaps around 1998 or so, I was
> present at a conversation between Guido and Tom Christiansen.  Tom asked
> Guido why Python didn't have closures, and Guido's reply (and I think
> this is an exact quote) was "Closures aren't important."
>
> I remember it because I was so astonished by the obtuseness of the
> answer.

I expect he still believes that.  I do too:  in Python, closures aren't
important.  Python eventually grew closures, and they're *nice* to have, but
it's always been possible to use Python's flexible classes to get the same
abilities, and it's even always been possible to get "real closures" via
abuse of Python's default-argument mechanism:

    def make_adder(n):
        def adder(i, n=n):
            return n+i
        return adder

    add5 = make_adder(5)
    add3 = make_adder(3)
    print add5(1), add3(1)

has printed 6 4 for eons.  This has too, replacing the function with a class
of the same name:

    class make_adder:
        def __init__(self, n):
            self.n = n

        def __call__(self, i):
            return self.n+i

It often proves much better to carry state around in explicit objects
instead of in hard to introspect, or to modify (unless you planned for that
from the start), anonymous closures.  In the above, I can easily introspect
to see what an instance of the make_adder class adds, and even change it if
I need to, and the class's author didn't need to anticipate either of those.
With the by-hand default-arg closure, introspection is still possible but
much harder, while mutation of what it does requires deep (and formally
undefined) wizardy.  With the current "real closure" version:

    def make_adder(n):
        return lambda i: n+i

introspection and mutation are both too painful to contemplate (of course
that inability to inspect or change is also a feature in some parts of some
apps -- usually brittle ones <0.9 wink>).

Closures can be much more convenient in the small (I think make_adder is a
good example of that); in the large, piles of nested closures are often more
a maintenance nightmare than a blessing, and especially when they're used to
maintain state more naturally modeled via classes.  Python doesn't need
closures -- they're just nice to have.

when-you-don't-have-a-hammer-only-nails-look-like-nails-ly y'rs  - tim






More information about the Python-list mailing list