[Python-Dev] Let's just *keep* lambda

Guido van Rossum guido at python.org
Thu Feb 9 19:33:10 CET 2006

Enough already.

As has clearly been proven, lambda is already perfect.


To those folks attempting to propose alternate syntax (e.g. x -> y):
this is the wrong thread for that (see subject). Seriously, I've seen
lots of proposals that just change the syntax, and none of them are so
much better than what we have. My comments on some recent proposals:

- <expr> for <formals>
Smells to much like a loop. And what if there are no formals? Also the
generalization from a generator without the "in <sequence>" part is
wrong; "f(x) for x in S" binds x, while the proposed "f(x) for x" has
x as a free variable. Very odd.

- <formals> -> <expr>
The -> symbol is much easier to miss. Also it means something
completely different in other languages. And it has some problems with
multiple formals: (x, y -> x+y) isn't very clear on the binding --
since '->' is an uncommon operator, there's no strong intuition about
whether ',' or '->' binds stronger. (x, y) -> x+y would make more
sense, but has an ambiguity as long as we want to allow argument
tuples (which I've wanted to take out, but that is also getting a lot
of opposition).

- lambda(<formals>): <expr>
This was my own minimal proposal. I withdraw it -- I agree with the
criticism that it looks too much like a function call.

- Use a different keyword instead of lambda
What is that going to solve?

- If there were other proposals, I missed them, or they were too far
out to left field to be taken seriously.


To those people complaining that Python's lambda misleads people into
thinking that it is the same as Lisp's lambda: you better get used to
it. Python has a long tradition of borrowing notations from other
languages and changing the "deep" meaning -- for example, Python's
assignment operator does something completely different from the same
operator in C or C++.


To those people who believe that lambda is required in some situations
because it behaves differently with respect to the surrounding scope
than def: it doesn't, and it never did. This is (still!) a
surprisingly common myth. I have no idea where it comes from; does
this difference exist in some other language that has lambda as well
as some other function definition mechanism?


To those people still complaining that lambda is crippled because it
doesn't do statements: First, remember that adding statement
capability wouldn't really add any power to the language; lambda is
purely syntactic sugar for an anonymous function definition (see above
myth debunking section). Second, years of attempts to overcome this
haven't come up with a usable syntax (and yes, curly braces have been
proposed and rejected like everything else). It's a hard problem
because switching back to indentation-based parsing inside an
expression is problematic. For example, consider this hypothetical

a = foo(lambda x, y:
      print x
      print y)

Should this be considered legal? Or should it be written as

a = foo(lambda x, y:
          print x
          print y

??? (Indenting the prints so they start at a later column than the 'l'
of 'lambda', and adding an explicit dedent before the close
parenthesis.) Note that if the former were allowed, we'd have
additional ambiguity if foo() took two parameters, e.g.:

a = foo(lambda x, y:
      print x
      print y, 42)

-- is 42 the second argument to foo() or is it printed?

I'd much rather avoid this snake's nest by giving the function a name
and using existing statement syntax, like this:

def callback(x, y):
    print x
    print y
a = foo(callback)

This is unambiguous, easier to parse (for humans as well as for
computers), and doesn't actually span more text lines. Since this
typically happens in a local scope, the name 'callback' disappears as
soon as as the scope is exited.

BTW I use the same approach regularly for breaking up long
expressions; for example instead of writing

a = foo(some_call(another_call(some_long_argument,
                  and_more(1, 2, 3),

I'll write

x = another_call(some_long_argument, another_argument)
a = foo(some_call(x, and_more(1, 2, 3)), and_still_more())

and suddenly my code is more compact and yet easier to read! (In real
life, I'd use a more meaningful name than 'x', but since the example
is nonsense it's hard to come up with a meaningful name here. :-)

Regarding the leakage of temporary variable names in this case: I
don't care; this typically happens in a local scope where a compiler
could easily enough figure out that a variable is no longer in use.
And for clarity we use local variables in this way all the time


Parting shot: it appears that we're getting more and more
expressionized versions of statements: first list comprehensions, then
generator expressions, most recently conditional expressions, in
Python 3000 print() will become a function... Seen this way, lambda
was just ahead of its time! Perhaps we could add a try/except/finally
expression, and allow assignments in expressions, and then we could
rid of statements altogether, turning Python into an expression
language. Change the use of parentheses a bit, and... voila, Lisp! :-)

--Guido van Rossum (home page: http://www.python.org/~guido/)

More information about the Python-Dev mailing list