Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

extended list comprehensions

9 views
Skip to first unread message

F. Jamitzky

unread,
May 26, 2002, 5:16:31 PM5/26/02
to
It would be great to have something like a list comprehension for the
reduce function. It would work in the same way as the comprehension
for the map function, which is:

[foo(x) for x in xs] <-is the same as-> map(foo,xs)

and maybe it could be written as:

{y=y+x for x in xs} <-would be-> reduce(operator.add,xs)

what do the experts think about that ?

ferdinand

Andrew Dalke

unread,
May 26, 2002, 6:58:29 PM5/26/02
to
F. Jamitzky:

>It would be great to have something like a list comprehension for the
>reduce function.
...

>and maybe it could be written as:
>
>{y=y+x for x in xs} <-would be-> reduce(operator.add,xs)

I use reduce so infrequently that I wouldn't think this is useful.
How often do you use it?

Your syntax is similar to "dictionary comprehensions" which have been
suggested several times, as in

{x:x*x for x in xs}

That's enough to make me believe your syntax would be confusing.
(As it is, 'reduce' is confusing.)

reduce takes an optional 3rd arg, as in

>>> reduce(operator.add, "test", "prefix-")
'prefix-test'
>>>

which I guess you would support as

y = "prefix-"


{y=y+x for x in xs}

But given that, if y doesn't exist before the {} is called, your
argument is that it should implicitly be set to 0. This then would
be one of the few places in Python with a default value, outside of
a function parameter definitions.

Andrew
da...@dalkescientific.com

Laura Creighton

unread,
May 26, 2002, 11:37:28 PM5/26/02
to
> --
> http://mail.python.org/mailman/listinfo/python-list

Adding more typography makes our language ugly and hard to read.

Laura Creighton


Greg Ewing

unread,
May 27, 2002, 1:13:30 AM5/27/02
to
Andrew Dalke wrote:
>
> y = "prefix-"
> {y=y+x for x in xs}
>
> But given that, if y doesn't exist before the {} is called, your
> argument is that it should implicitly be set to 0. This then would
> be one of the few places in Python with a default value, outside of
> a function parameter definitions.

Hmmm, maybe something like

(y = y + x for x in xs from y = 0)

Or maybe not. I think this sort of thing is just
too rare to be worth a special syntax, as much
fun as it may be devising one!

--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg

Bernhard Herzog

unread,
May 27, 2002, 9:15:54 AM5/27/02
to
f...@hotmail.com (F. Jamitzky) writes:

> It would be great to have something like a list comprehension for the
> reduce function. It would work in the same way as the comprehension
> for the map function, which is:
>
> [foo(x) for x in xs] <-is the same as-> map(foo,xs)
>
> and maybe it could be written as:
>
> {y=y+x for x in xs} <-would be-> reduce(operator.add,xs)


Well, one could mimic reduce with the side-effects of a list
comprehension:

>>> y = 0
>>> xs = range(10)
>>> [0 for x in xs for y in [y + x] if 0]
[]
>>> y
45

Not recommended, though :-)


Bernhard

--
Intevation GmbH http://intevation.de/
Sketch http://sketch.sourceforge.net/
MapIt! http://www.mapit.de/

Bengt Richter

unread,
May 27, 2002, 5:03:37 PM5/27/02
to
On 27 May 2002 15:15:54 +0200, Bernhard Herzog <b...@intevation.de> wrote:

>f...@hotmail.com (F. Jamitzky) writes:
>
>> It would be great to have something like a list comprehension for the
>> reduce function. It would work in the same way as the comprehension
>> for the map function, which is:
>>
>> [foo(x) for x in xs] <-is the same as-> map(foo,xs)
>>
>> and maybe it could be written as:
>>
>> {y=y+x for x in xs} <-would be-> reduce(operator.add,xs)
>
>
>Well, one could mimic reduce with the side-effects of a list
>comprehension:
>
>>>> y = 0
>>>> xs = range(10)
>>>> [0 for x in xs for y in [y + x] if 0]
>[]
>>>> y
>45
>
>Not recommended, though :-)
>

That is really evil ;-) Enough so to want a private scope
to prevent side effects for list comprehensions.

I wonder how much code would break, not counting horrible examples
concocted just for the sake of messing around.

BTW, I wonder if reduce would get more use if it had a more suggestive
name and mnemonic keyword arguments, e.g.,

>>> def accumulate(**kw):
... return reduce(
... kw.get('f_acc_delta', lambda a,d: a+d),
... kw.get('seq',[]),
... kw.get('start_with', 0)
... )
...
>>> accumulate(seq=range(10))
45
>>> accumulate(seq=range(4),f_acc_delta=lambda a,d: a+d*d)
14
>>> accumulate(seq='abc', start_with='XXX:')
'XXX:abc'

or maybe def accumulate(seq, **kw): ...

Regards,
Bengt Richter

Raymond Hettinger

unread,
May 28, 2002, 9:50:33 AM5/28/02
to
"F. Jamitzky" <f...@hotmail.com> wrote in message
news:f32195af.02052...@posting.google.com...

> It would be great to have something like a list comprehension for the
> reduce function. It would work in the same way as the comprehension
> for the map function, which is:
>
> [foo(x) for x in xs] <-is the same as-> map(foo,xs)
>
> and maybe it could be written as:
>
> {y=y+x for x in xs} <-would be-> reduce(operator.add,xs)

Perhaps this syntax would be cleaner:

for x in xs: y=y+x

Raymond Hettinger


Kragen Sitaker

unread,
May 28, 2002, 6:19:24 PM5/28/02
to
"Andrew Dalke" <da...@dalkescientific.com> writes:
> F. Jamitzky:
> >It would be great to have something like a list comprehension for the
> >reduce function.
> ...
> >and maybe it could be written as:
> >
> >{y=y+x for x in xs} <-would be-> reduce(operator.add,xs)
>
> I use reduce so infrequently that I wouldn't think this is useful.
> How often do you use it?

Not as often as I could. It's general enough that just about any
aggregate operation can be expressed in terms of it, usually as simply
as it could be in a loop, and often more simply.

As a simple example, see
http://lists.canonical.org/pipermail/kragen-hacks/2002-May/000343.html
for 'map' and 'filter' are expressed in terms of 'reduce', in Python
and Common Lisp.

> That's enough to make me believe your syntax would be confusing.
> (As it is, 'reduce' is confusing.)

Which is probably why it's not used as much as it could be...

> But given that, if y doesn't exist before the {} is called, your
> argument is that it should implicitly be set to 0. This then would
> be one of the few places in Python with a default value, outside of
> a function parameter definitions.

If reduce doesn't get a 'start' argument, it starts with y set to the
first item in the list; you could do the same for "reduce
comprehensions".

That said, I think "reduce comprehensions" as presented are a terrible
idea; unlike list comprehensions, they are not an improvement in
readability over the corresponding explicit loop, and they are not an
improvement in readability over the corresponding call to 'reduce'.

Steve Horne

unread,
May 30, 2002, 1:28:24 PM5/30/02
to

At the moment, the following are syntax errors in Python...

[ a = a + b for b in c ]
[ a += b for b in c ]

so there is certainly no need to create confusion with the dictionary
syntax by using braces.

I would suggest including the start value as well, in a form similar
to...

[ a = 0 then a += b for b in c ]

or maybe...

[ a = 0; a += b for b in c ]

As someone who makes heavy use of list comprehensions and reduce
functions in a context which cannot be easily replaced with for loops,
I would certainly use a feature like this. It is both clearer and more
powerful than the current reduce function in one hit - more powerful
because it allows a cross product and an if condition to be combined
into the 'reduce'. I also have problems remembering the order of
parameters for reduce (and map and filter), and this form would remove
that problem as well.

The only thing I particularly dislike is the fact that enclosing the
expression in '[' and ']' suggests that the result is a list, just as
using '{' and '}' suggests the result is a dictionary. That might
imply that a 'reduce comprehension' should be written as...

( a = 0; a += b for b in c )

the notation being intended to imply a parenthesised subexpression,
but even that could cause problems if someone suggests tuple
comprehensions (maybe for being potentially faster than list
comprehensions in cases where tuples are appropriate).

The reason I can't easily translate to for loops is because I have a
code preprocessor which can conveniently insert fragments into an
expression (so the return value goes to the right place), but which
cannot easily find a safe place to put an equivalent for loop or
function, or a safe variable to store the result in.

I know it's very LISP-ish, but I do like to have everything usable
within an expression precisely because of this localisation effect,
but I admit that there would be little or no benefit for hand-written
code.

Even so, I'll suggest one item from my wish-list and how it could be
adapted to make 'reduce comprehensions' redundant...

First, I'd like to be able to use imperative code within parentheses.
Statements would be separated by semicolons (which can already be used
to put several statements on a line), but the last semicolon would be
followed by an expression for the result (or maybe a return statement
should be used).

For example...

print (x = "Hello"; x)

In itself, this is pointless. However, next I'd suggest that the
list-comprehension style syntax could potentially make sense as a loop
shorthand for statements...

y = 0

# Add all ints < 100 that are divisible by three
Y += i for i in range (100) if i % 3 == 0

Combining these ideas, 'reduce comprehensions' would not need to be
directly supported as you could use...

print (y=0; y+=i for i in range(100) if i % 3 == 0; y)


I confidently predict that a lot of people will hate this idea with a
passion ;-)

--
Steve Horne
st...@lurking.demon.co.uk

Oliver Steele

unread,
Jun 1, 2002, 6:36:01 AM6/1/02
to
f...@hotmail.com (F. Jamitzky) wrote in message news:<f32195af.02052...@posting.google.com>...

What about using ellipsis? These could do foldl (reduce):
...+x for x in xs
operator.add(..., x) for x in xs

This leaves an obvious extension for foldr (reduce from the right):
swap the identifier and the ellipsis:
x+... for x in xs
operator.add(x, ...) for x in xs

The bug in this (putting aside the question of whether it's worth
adding anything to the language) is that it suggests that ... is a way
to write curry (similar to (x+) and (+x) in Haskell), and then:
[...+x for x in xs]
becomes ambiguous between a singleton list containing a reduction, and
a list of lambdas. Any way to save this?

0 new messages