Lambda in Python 3000

, ,

On Guido van Rossum's blog site is a essay The fate of reduce() in Python 3000 @ Source www.artima.com. He muses with the idea that he would like to remove {lambda, reduce, filter, map} functions in a future version Python 3000.

Guido wrote:

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, ⁖ 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)

The form [x for x in S if P(x)] is certainly not more clear than filter(P, S). The latter is clearly a function, what is the former? A function every programer in any language can understand and appreciate its form and function. Why would anyone to expect everyone to appreciate a Python syntactical idiosyncrasy [… for … in … if …]?

Also, the argument that the form filter(F,S) being cumbersome because the first argument is a function and that mostly likely it would be a function that returns true/false thus most people will probably use the inline “lambda” construct and that is quite cumbersome than if the whole thing is written with the syntactical idiosyncrasy [… for … in … if …], is rather inane, as you can now see.

The filter(decisionF, list) form is clean, concise, and helps thinking. Why does it help thinking? Because it condenses the whole operation into its mathematical essence with the most clarity. That is, it filters, of a list, and by a yes/no decision function. Nothing is more, and nothing can be less. It is unfortunate that the decision function usually goes by the name “predicate”, and often written in a syntax construction called “lambda”. These are un-intuitive jargons developed by the tech geekers of the functional programing community, out of historical reasons. (The term “predicate” came from the field of logic, and the term “lambda” came from a branch of logic called “lambda calculus”, because the guy happened to use the greek letter λ as notation.). The lambda could be more intuitively renamed as Function (as with Mathematica and JavaScript) and the Predicate could be called Decision Function.

If the predicate P in filter(P,S) is cumbersome, so would exactly the same thing appear in the syntactical idiosyncrasy: [x for x in S if P(x)].

Guido added this sting as a afterthought:

(plus the lambda is slower than the list comprehension)

Which is faster is really the whim and capacity of Python compiler implementators. And, weren't we using clarity as the judgement a moment ago? The concept of a function every programer understands, but what the heck is a List Comprehension? Why don't you scrap list comprehension in Python 3000 and create a table() function that's simpler in syntax and more powerful in semantics? 〔☛ List Comprehension in Python & Perl

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

In the outset Guido here assumes a moronitude about the set of Python users and what they are familiar of. Python users 10 years ago are not the same Python users today, and will certainly not be the same 10 years later if you chop off lambda. Things change, math literacy advances, and what users you have changes with what you are. A function is the gist of a mathematical idea embodied in computer languages, not something from LISP or Scheme as tech geekers wont to think.

… there is a widespread misunderstanding that lambda can do things that a nested function can't …

One is so insulted by a industrial big shot in quoting something so disparate then shot it down as if showing his perspicacity.

A lambda is a syntax for function or a name for the concept of function. What does it mean that a lambda isn't as powerful as nested function??

The lambda in Python is really ill. It is designed with a built-in limitation in the first place, and regarded as some foreign substance in the Imperative Crowd such as the Pythoners. If there's any problem with lambda, it is with lambda in Python and Pythoner's attitude.

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;

Of course, one begins to write things like Java: in three thousand words just to show you are a lamo.

The removing of elements in a language is in general not a good idea. Removing powerful features so that coding monkeys can use it is moronic. (⁖ Java) Removing “redundant” constructs is not always smart (⁖ Scheme), because it pinches on practicality. Removing existing language features by a visionary upgrade is a waste. It forces unnecessary shakeup and can cause death.

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.

The existence of reduce() in Python is probably caused by tech geeking clowns of the computing industry. Basically, nobody really have a clear understanding of mathematics or computing semantics, but every elite tech geeker knew one bag of constructs of various languages. So, you add this, i want that, and the language becomes a incoherent soup of constructs, with the backlash of wanting to chop off things again, with that good things.

reduce() in fact embodies a form of iteration/recursion on lists, very suitable in a functional language environment. If Python's lambda and other functional facilities are more powerful or complete, reduce() would be a good addition. For instance, in functional programing, it is a paradigm to nest or sequence functions. (most readers will be familiar in the form of unix shell's “pipe”). When you sequence functions, you can't stop in the middle and do a loop construct. So, reduce() and other functional forms of iteration are convenient and necessary.

Suggestions: lambda, reduce(), filter() and map() all should stay. I'm not sure exactly what's the ins and outs of Python 3000. If one wants to shake things up based on a vision: don't. There are already gazillion languages and visions; the world really don't need another bigshot's say for their personal advancement. As for improvement, lambda in Python should be expanded to remove its one-argument limitation (and Imperative Programing Crowd such as Pythoners should cease and desist with their lambda attitude problem). The function map() could also be considered for expansion. 〔☛ What is Expressiveness in a Computer Language〕 Function reduce() should stay because it's already there, even if it is not very useful and odd in Python. filter() should stay as it is as it is superb and proper.

General Loop Constructs in Fuctional Ways

Here i will try to illuminate some miscellaneous things regarding the lambda in Python issue.

As i have explained in the essay List Comprehension in Python & Perl, the so-called List Comprehension is just a irregular syntax to facilitate generating lists. The name is a terrible jargon, and the means is also bent. The proper name should be something like List Generating Form, and the proper means should be the plain function. 〔☛ Computer Language Design: What's List Comprehension and Why is It Harmful?

For instance, Python's range() is such a list generator, only that it is limited in scope.

For a example of a powerful list generator, see Mathematica's Table function. Mathematica: Table

Note Table's power in generating not just flat lists, but trees (nested lists). And if one really want flat lists, there's the Flatten function that flats any nested lists. (Python should have this too) It is far easier to change a tree to a flat list, then partitioning a flat list into nested list.

Python's reduce() is Mathematica's Fold. Mathematica: Fold

Besides Fold, in Mathematica there's also, Nest, FixedPoint, and others. Nest[f, x, n] recursively applies a function to itself n times, starting with x. FixedPoint[f, expr] recursively applies a function to itself until the result no longer changes (or when a optional function returns true). Each of {Nest, FixedPoint, Fold} have a corresponding version {NestList, FixedPointList, FoldList} with name ending in “List”. They return a list, containing all the steps. ⁖ NestList[f,x,3] returns {x, f[x], f[f[x]], f[f[f[x]]]}. Mathematica: Nest Mathematica: FixedPoint

All these can be written as a For loop, but they make the code condensed and meaning clear. More so, they are important when programing in a functional style. In functional programing, you don't litter lots of variables or intermediate loops here or there on every other line. The code is usually tight and inline. When sequencing a series of functions 〔☛ Unix Pipe as Functional Language〕, you can't stop in the middle and do a block of loop. All these are made inlined into a function. (i.e.: constructed as “lambda”) A block of code usually corresponds to a unit of the algorithm used, as opposed to a block of implementation. You don't read the minute details of the code. You read the algorithmic unit's inline doc, or just the input and output of a code block.

Also, these inline loop constructs are not only suitable for computing numbers as Guido ignorantly thought. They are functional forms of generic loop constructs. Their first argument is a function, and second argument is a list. Their generality lies with the fact that their first argument is a function. If a language does not provide a convenient way to represent the concept of a function, then these functional loop construct's usability will suffer.

The Pythoners, did not provide a convenient way to represent a function. (they tried, with their limited implementation of lambda and shun it like a plague)

The way Guido puts it gives us a nice glimpse of their retarded mentality:

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;

As we can see here, in Pythoner's mind, lambda is for “very short local functions”.

Python's limited lambda and imperative programer's unfamiliarity of it made functional programing suffer in Python. Consequently, it is not surprising for one to feel a need to chop off things unfamiliar.

For Python's map(), look at Mathematica's Map on how it might be extended. Mathematica: Map

Note the ability to map to not just flat lists but trees (nested lists). Note the power of expressing the concept of levels of a tree.

For Python's filter(), check out the equivalent in Mathematica's Select: Mathematica: Select

Note how it provides a third option for picking just the first n items. Also note, that Select is just a way to pick elements in a list. Mathematica provides a set to do these: Part, Take, Drop, Select, Cases, Delete, DeleteCases …. All uniformly use the function syntax and all returns a new list. In Python and other imperative clown's languages, usually they provide a limited varieties to do such a task, and also inconsistent as if piled on. (⁖ In Python we have alist[5:9], filter(f,alist), alist.remove(…), del alist[…]. Some modify the list in-place, some returns a new list.)

Which Lispstick to Wear in Your Language?

One is quite sorry to read a big shot contemplating on petty issues with a ambitious name Python THREE THOUSAND.

For the grand Python THREE THOUSAND, what about supporting non-trivial things such as exact fractions? What about a built-in worry-free exact-arithmetics once for all? What about supporting pattern matching for expression structures? What about supporting Unicode in variable and function names? 〔☛ Unicode Support in Ruby, Perl, Python, JavaScript, Java, Emacs Lisp, Mathematica

The features of Mathematica mentioned above existed over a decade ago. But today, OpenSourcing bigwigs can contemplate and dither nothing but which lipstick to use.

A good number of the industrial dignitaries are selfish liers. And today we have the most human-labor intensive language Java and the crazily hacked up Perl and their bosses trumpeting them as state-of-the-art.

Sometimes i get turned off by Stephen Wolfram's megalomaniacal cries, but in many ways, i think his statements about the moronicities of the academicians and otherwise dignitaries are justified.

(disclaimer: all mentions of any real person are opinion.)

The required techniques of effective reasoning are pretty formal, but as long as programming is done by people that don't master them, the software crisis will remain with us and will be considered an incurable disease. And you know what incurable diseases do: they invite the quacks and charlatans in, who in this case take the form of Software Engineering gurus.

—Edsger Dijkstra (1930 〜 2002) in EWD 1305

For a mockery of Guido's essay by PLT Scheme lisp folks, see: The Fate of Lambda in Python 3000 and Scheme v300.

blog comments powered by Disqus