[BangPypers] if not with comparision statement in python

Dhananjay Nene dhananjay.nene at gmail.com
Tue Aug 2 09:13:38 CEST 2011


On Tue, Aug 2, 2011 at 11:12 AM, Anand Balachandran Pillai
<abpillai at gmail.com> wrote:
> On Mon, Aug 1, 2011 at 7:51 PM, Dhananjay Nene <dhananjay.nene at gmail.com>wrote:
>
>> On Mon, Aug 1, 2011 at 7:26 PM, Anand Balachandran Pillai
>> <abpillai at 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


More information about the BangPypers mailing list