On Tue, Aug 2, 2011 at 11:12 AM, Anand Balachandran Pillai <abpil...@gmail.com> wrote: > On Mon, Aug 1, 2011 at 7:51 PM, Dhananjay Nene > <dhananjay.n...@gmail.com>wrote: > >> On Mon, Aug 1, 2011 at 7:26 PM, Anand Balachandran Pillai >> <abpil...@gmail.com> wrote: >> > IMHO, map/filter/reduce and the inevitable companion lambda were >> > added on to Python when it was still trying to find its identity on >> where >> > it stood in the pantheon of dynamic typed languages - since it wanted >> > to be everything for everyone it borrowed some of these constructs >> > from Lisp or other functional languages. >> > >> > With addition of list comps, generators etc, these right now stand >> > out like sore thumbs in the language and should be got ridden >> > of at the earliest. >> >> I am certain there are contrary opinions, even though the BDFL has >> weighed in. So yes, python is unlikely to be the playground for these >> constructs. I find a degree of elegance and utility to these >> constructs, though it is as well likely that these may seem like sore >> thumbs to others. >> > > I also used to think likewise when I first encountered these functions > when I was playing around with Python many years back. > > However, I think the "elegancy" is actually a myth and is perhaps > a pseudonym for being cryptic. > > For example, look at these competing solutions for summing > the squares of first 10 integers. > > 1. List comp > > >>> sum([x*x for x in range(10)]) > 285 > > 2. Map > > >>> sum(map(lambda x: x*x, range(10))) > 285 > > 3. Reduce > > >>> reduce(lambda x,y: x + y*y, range(10)) > 285 > > I dont think there will be much disagreement that the listing is also in the > order > of decreasing readability.
There is a risk of conflating three different aspects together a. Syntax b. Runtime c. Concepts It is understandable that these get conflated in a mailing list specific to one language and thats fine. But I need to elaborate on the difference, since that difference is important given that the elegance is being contested. a. Syntax : I am pretty darned sure - in python the syntax when using functions like map reduce, can sometimes be quite odd. The List comprehension syntax is succinct and natural. To that end, I immediately clarified in the thread earlier where I suggested that <blockquote> def in_range(number, min_max_pairs): return any(x <= number <=y for x, y in min_max_pairs) </blockquote> was syntactically superior to <blockquote> def in_range(number) : return any(map(lambda (x,y) : x <= number <= y, ((0,10),(11,20), (21,30), (31,40)))) </blockquote> 2. Runtime : There's a discussion on the mailing list about how the runtime influences the performance. Thats adequate reference to the topic 3. Concepts : I insist the concepts are extremely elegant (which is what I meant when I referred to elegance earlier). I mentioned another example from scala : <blockquote> println(0 to 4 map {_ * 2} map {_ + 1} reduce {_ + _}) </blockquote> It would be interesting to contrast the above in terms of syntax (expressivity), runtime (absolute runtime performance) and concepts with <blockquote> print sum(n * 2 + 1 for n in range(5)) </blockquote> It is my perception that both are readable. The python version is a bit more concise as well. The key part (which I emphasised a bit earlier) is composition. While the python version is based out of a particular syntax which assembles the entire logic as one construct, the scala version is based on composition of smaller constructs, each being an independent function (FWIW scala also has an equivalent which is referred to as the for comprehension). This is but one reason why I find functional constructs more elegant. This elegance is not a myth, and I find the ability to compose a program out of smaller building blocks appealing. As the problems become bigger (than few liners), this elegance starts becoming quite powerful. And I think it helps all programmers python or otherwise to use these constructs in their thought process. Which is where I again meant functions like map are quite atomic and portable. So the entire reason why I lay this out in great detail is that I believe - some programmers will be better served as they start understanding these constructs. > > The list comp solution is graspable at one look, the map one takes one > step of mental computation and the reduce one takes a few mental hoops > to jump through and is utterly confusing to anyone not familiar with > list/functional programming. Absolutely. But just take a look at the scala version - that is not true. So the issue isn't with the concepts. Its not even an issue with prefix/postfix or object being a destination of a method call (a la ruby blocks). Since haskell has a nice syntax for composing functions without making map an operator/method or making any changes from a prefix/postfix perspective. > The reduce one is also very error prone. For example, a small mistake > such as, > >>>> reduce(lambda x,y: x*x + y, range(10)) > 2818129390158170901506703075470572449397357853477615482257305306043465L > > Produces a monstrosity instead of the expected answer. (umm .. so would an equivalent list comprehension) .. perhaps I didn't understand. > Perhaps those with a LISP/functional background find some mathematical > elegance with these solutions. But from a pure Python perspective, > they lack any elegance whatsoever. But that doesn't need to stop python programmers thinking using such constructs and using them as appropriate. I still continue to find use cases where I prefer using them in python. FWIW I tend to end up using list comprehensions more frequently. Dhananjay _______________________________________________ BangPypers mailing list BangPypers@python.org http://mail.python.org/mailman/listinfo/bangpypers