[Python-ideas] Reduce/fold and scan with generator expressions and comprehensions

David Mertz mertz at gnosis.cx
Tue Oct 25 21:36:28 EDT 2016


On Tue, Oct 25, 2016 at 1:55 PM, Rob Cliffe <rob.cliffe at btinternet.com>
wrote:
>
> >>> [prev * k for k in [5, 2, 4, 3] from prev = 1]
> [1, 5, 10, 40, 120]
>
> That makes sense for me, and seem simpler than:
>
> >>> from itertools import accumulate, chain
> >>> list(accumulate(chain([1], [5, 2, 4, 3]), lambda prev, k: prev * k))
> [1, 5, 10, 40, 120]
>
> Well, if you want an instant reaction from someone skimming this thread: I
> looked at the first example and couldn't understand it.
>

After reading every post in the thread, I still don't understand the
proposed new syntax really.

How does 'prev' get bound in the loop? Is it a new magic keyword for "last
accumulated element?" Does the binding in the "from" clause magically say
that it should get rebound in the loop where it's no longer mentioned? Why
is the word `from` used here when there's no obvious relation to other uses?

The alternate version looks much better if you don't try so hard to make it
look bad.  The much more obvious spelling is:

from operator import mul

from itertools import accumulate, chain

accumulate(chain([1], nums), mul)


If you give up a fear of using `import` and stop arbitrarily converting a
possibly infinite iterator to a concrete list, this form is extremely short
and obvious.  Moreover, in the example, it is extra strange that the
multiplicative identity is added into the front of the iterator.  This is
exactly the same thing as simply spelling it:

accumulate(nums, mul)

Which is even shorter.  It's feels very artificially contrived to insist
that the initial element must live somewhere other than the iterator
itself.  But it would be easy enough to write a wrapper to massage an
iterator for this special case:

def prepend(item, it):

    return itertools.chain([item], it)


Doesn't save any characters, but the name might emphasize the intent.
Maybe this implementation forces the point even more:

def prepend(item, it):

    yield item

    yield from it


-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20161025/2147bf8f/attachment.html>


More information about the Python-ideas mailing list