The Fate of Lambda in Python 3000 and Scheme v300

By Xah Lee. Date:

On 2005, Guido, the creator of Python, wrote on his blog of this piece:

[The fate of reduce() in Python 3000 By Guido van Rossum. At http://www.artima.com/weblogs/viewpost.jsp?thread=98196 , accessed on 2010-09-22 ]

Excerpt:

About 12 years ago, Python aquired lambda, reduce(), filter() and map(), courtesy of (I believe) a Lisp hacker who missed them and submitted working patches. But, despite of the PR value, I think these features should be cut from Python 3000.

I think dropping filter() and map() is pretty uncontroversial; filter(P, S) is almost always written clearer as [x for x in S if P(x)], and this has the huge advantage that the most common usages involve predicates that are comparisons, for example, x==42, and defining a lambda for that just requires much more effort for the reader (plus the lambda is slower than the list comprehension). Even more so for map(F, S) which becomes [F(x) for x in S]. Of course, in many cases you'd be able to use generator expressions instead.

Why drop lambda? Most Python users are unfamiliar with Lisp or Scheme, so the name is confusing; also, there is a widespread misunderstanding that lambda can do things that a nested function can't — I still recall Laura Creighton's Aha!-erlebnis after I showed her there was no difference! Even with a better name, I think having the two choices side-by-side just requires programmers to think about making a choice that's irrelevant for their program; not having the choice streamlines the thought process. Also, once map(), filter() and reduce() are gone, there aren't a whole lot of places where you really need to write very short local functions; Tkinter callbacks come to mind, but I find that more often than not the callbacks should be methods of some state-carrying object anyway (the exception being toy programs).

So now reduce(). This is actually the one I've always hated most, because, apart from a few examples involving + or *, almost every time I see a reduce() call with a non-trivial function argument, I need to grab pen and paper to diagram what's actually being fed into that function before I understand what the reduce() is supposed to do. So in my mind, the applicability of reduce() is pretty much limited to associative operators, and in all other cases it's better to write out the accumulation loop explicitly.

There aren't a whole lot of associative operators. (Those are operators X for which (a X b) X c equals a X (b X c).) I think it's just about limited to +, *, &, |, ^, and shortcut and/or. We already have sum(); I'd happily trade reduce() for product(), so that takes care of the two most common uses. The bitwise operators are rather specialized and we can put fast versions in a library module if there's demand; for shortcut booleans I have the following proposal.

On 2005-04-01, Shriram Krishnamurthi, one of the main member behind the PLT Scheme lisp team (now named Racket), posted the following in their mailing list. http://article.gmane.org/gmane.comp.lang.lightweight/3240

The Fate of LAMBDA in PLT Scheme v300

or Lambda the Ultimate Design Flaw

About 30 years ago, Scheme had FILTER and MAP courtesy of Lisp hackers who missed them from their past experience. To this collection, Scheme added a lexically-scoped, properly-functioning LAMBDA. But, despite of the PR value of anything with Guy Steele's name associated with it, we think these features should be cut from PLT Scheme v300.

We think dropping FILTER and MAP is pretty uncontroversial; (filter P S) is almost always written clearer as a DO loop (plus the LAMBDA is slower than the loop). Even more so for (map F S). In all cases, writing the equivalent imperative program is clearly beneficial.

Why drop LAMBDA? Most Scheme users are unfamiliar with Alonzo Church (indeed, they don't even know that he was related to Guy Steele), so the name is confusing; also, there is a widespread misunderstanding that LAMBDA can do things that a nested function can't — we still recall Dan Friedman's Aha! after we showed him that there was no difference! (However, he appears to have since lapsed in his ways.) Even with a better name, we think having the two choices side-by-side just requires programmers to think about their program; not having the choice streamlines the thought process, and Scheme is designed from the ground up to, as much as possible, keep programmers from thinking at all.

So now FOLD. This is actually the one we've always hated most, because, apart from a few examples involving + or *, almost every time we see a FOLD call with a non-trivial function argument, we have to grab pen and paper and imagine the *result* of a function flowing back in as the *argument* to a function. Plus, there are *more* arguments coming in on the side! This is all absurdly complicated. Because almost all the examples of FOLD we found in practice could be written as a simple loop with an accumulator, this style should be preferred, perhaps with us providing a simple helper function to abstract away the boilerplate code. At any rate, FOLD must fold.

— The PLT Scheme Team

For detailed criticism of Guido's essay, see: Lambda in Python 3000 .

see also: Why Python Lambda is Broken and Can't be Fixed