a potential pep to extend the syntax of for loops

Chris Rebert clp2 at rebertia.com
Mon Mar 9 05:52:47 EDT 2009


On Mon, Mar 9, 2009 at 2:15 AM, pang <pablo.angulo at uam.es> wrote:
>  Hello,
>  This is an idea about something I'd like to see implemented in
> python.
> I understand that's the purpose of PEPs, so I'll write it as a PEP,
> but
> send it here to receive your valuable feedback.
>
> Abstract
>
> This is a proposal to increase the richness of for loops, only to the
> extent that it equals that of list and generator comprehensions. In
> the
> opinion of the proponent, this will make the language more uniform and
> would reduce the excessive level of nesting that is required
> sometimes,
> without introducing special keywords, or breaking backwards
> compatibility.
>
> This PEP is independent of, but related to PEP 3142.
>
> Rationale
> The syntax of a for loop is restricted to the following:
>>>>    for element in list:
>>>>        instructions
>
> Nesting for loops and conditionals is possible, of course:
>>>>    for x in list1:
>>>>        for y in list2:
>>>>            if condition(x,y):
>>>>                func2(x,y)
>
> However, for list and generator comprehensions, the syntax is more
> concise:
>>>>    list=[func(x,y,..) for x in list1 for y in list2 ... if
> condition(x,y,...)]
>
> Loops and comprehensions serve for similar purposes, and sometimes
> what
> was first written in one way is finally changed into the other. Thus
> it
> would be convenient to allow for more similar syntax in both of them.
> This requires that the syntax of a for loop allows for nested for and
> conditionals (and possibly while loops (see PEP 3142))
>
>>>>for x in list1 for y in list2 ... if condition(x,y,...):
>>>>     ''instructions''
>
> In general, whenever
>>>> [expression1  iterator]
> is a valid list comprehension, then
>>>> iterator:
>>>>     statements
> should be a valid loop.
>
> As another example, it is sometimes the case that an iteration over
> two
> lists can be rewritten as a single iteration:
>>>>         for x in range(10) for y in range(10)  if x+y==5:
>>>>             print x,y
> is equivalent to
>>>>         for x in range(6):
>>>>             print x,5-y
> it is somewhat more conceptual to think of the first iteration as a
> single loop.
>
> It is actually possible to come very close to the notation proposed
> using the generator comprehensions introduced in python 2.5:
>>>>         for x,y in ((x,y) for x in range(10) for y in range(10)  if
> x+y==5):
>>>>             print x,y
> but this notation is cumbersome.
>
> This PEP responds to the philosophy that if a nesting level is unused,
> it should be avoided. For example, in the code:
>
>>>> for x in list1:
>>>>     func1(x)
>>>>     for y in list2:
>>>>        if cond(x,y):
>>>>           func(x,y)
>>>>     func3(x)
>
> the second nesting  level doesn't contain any statements and thus,
> should this PEP be passed, it should be written:
>
>>>> for x in list1:
>>>>     func1(x)
>>>>     for y in list2 if cond(x,y):
>>>>           func(x,y)
>>>>     func3(x)

This syntax sugar seems to be too sweet, to the point that it causes
*cavities* IMHO.
It seems Perlish (always a bad sign), quite similar to how Perl lets
you add 'if' and 'while' suffixes to statements; it undermines the
uniformity and simplicity of Python's syntax.

The extra indentation and nesting level is useful in that it
unambiguously indicates what order the for-loops are nested in. Also,
if the loop body of the outer loop ever becomes more complicated
beyond just containing an inner loop, the lines are easily added,
whereas this proposal would require a more drastic and complicated
splitting back up of the loop statement.

Though list comprehensions and for-loops are indeed closely related,
this is one instance where there shouldn't be a middle ground of
comprehension-like for-statements because it complicates things too
much. It's like with if-elif-else and the ternary operator -- one is
for very simple cases, and one is for anything else; anything in
between makes it harder to choose and makes the right choice in a
situation more ambiguous. Python is not Lisp and `for` is not the DO
macro ;-).

I'll conclude by citing the Zen: "Special cases aren't special enough
to break the rules."
And secondly: "There should be one-- and preferably only one --obvious
way to do it."
This PEP seems to break both these principles without enough of a gain
to have "practicality beat purity".

-1 for me on this (not that I'm entitled to cast a vote :-).

Cheers,
Chris

-- 
I have a blog:
http://blog.rebertia.com



More information about the Python-list mailing list