A critic of Guido's blog on Python's lambda

Alex Martelli aleax at mac.com
Thu May 11 03:16:24 CEST 2006


Joe Marshall <eval.apply at gmail.com> wrote:

> Alex Martelli wrote:
> > Joe Marshall <eval.apply at gmail.com> wrote:
> >    ...
> > > The problem is that a `name' is a mapping from a symbolic identifier to
> > > an object and that this mapping must either be global (with the
> > > attendant name collision issues) or within a context (with the
> > > attendant question of `in which context').
> >
> > Why is that a problem?  Even for so-called "global" names, Python
> > supports a structured, hierarchical namespace, so there can never be any
> > collision betwen the "globals" of distinct modules (including modules
> > which happen to have the same name but live in distinct packages or
> > subpackages) -- I did mention that names could usefully be displayed in
> > some strcutured form such as apackage.somemodule.thefunction but perhaps
> > I was too tangential about it;-).
> 
> Can you refer to inner functions from the global context?  Suppose I
> have this Python code:
> 
> def make_adder(x):
>     def adder_func(y):
>         sum = x + y
>         return sum
>     return adder_func
> 
> Can I refer to the inner adder_func in any meaningful way?

You can refer to one instance/closure (which make_adder returns), of
course -- you can't refer to the def statement itself (but that's a
statement, ready to create a function/closure each time it executes, not
a function, thus, not an object) except through introspection. Maybe I
don't understand what you mean by this question...


> > If I used continuations (I assume you mean in the call/cc sense rather
> > than some in which I'm not familiar?) I might feel the same way, or not,
> > but I don't (alas), so I can't really argue the point either way for
> > lack of real-world experience.
> 
> I meant continuations as in the receiver function in
> continuation-passing-style.  If you have a function that has to act
> differently in response to certain conditions, and you want to
> parameterize the behavior, then one possibility is to pass one or more
> thunks to the function in addition to the normal arguments.  The

Ah, OK, I would refer to this as "callbacks", since no
call-with-continuation is involved, just ordinary function calls; your
use case, while pretty alien to Python's typical style, isn't all that
different from other uses of callbacks which _are_ very popular in
Python (cfr the key= argument to the sort methods of list for a typical
example).  I would guess that callbacks of all kinds (with absolutely
trivial functions) is the one use case which swayed Guido to keep lambda
(strictly limited to just one expression -- anything more is presumably
worth naming), as well as to add an if/else ternary-operator.  I still
disagree deeply, as you guessed I would -- if I had to work with a
framework using callbacks in your style, I'd name my callbacks, and I
wish Python's functools module provided for the elementary cases, such
as:

def constant(k):
    def ignore_args(*a): return k
    return ignore_args

def identity(v): return v

and so on -- I find, for example, that to translate your

> (define (option3 key table default-value)
>   (lookup key table
>     (lambda (value) value)
>     (lambda () default-value)))

I prefer to use:

def option3(key, table, default_value):
    return lookup(key, table, identity, constant(default_value))

as being more readable than:

def option3(key, table, default_value):
    return lookup(key, table, lambda v: v, lambda: default_value)

After all, if I have in >1 place in my code the construct "lambda v: v"
(and if I'm using a framework that requires a lot of function passing
I'm likely to be!), the "Don't Repeat Yourself" (DRY) principle suggests
expressing the construct *ONCE*, naming it, and using the name.

By providing unnamed functions, the language aids and abets violations
of DRY, while having the library provide named elementary functions (in
the already-existing appropriate module) DRY is reinforced and strongly
supported, which, IMHO, is a very good thing.


Alex



More information about the Python-list mailing list