[Python-ideas] Proposal: A Reduce-Map Comprehension and a "last" builtin
Steven D'Aprano
steve at pearwood.info
Thu Apr 5 20:29:19 EDT 2018
On Thu, Apr 05, 2018 at 06:24:25PM -0400, Peter O'Connor wrote:
> Well, whether you factor out the loop-function is a separate issue. Lets
> say we do:
>
> smooth_signal = [average = compute_avg(average, x) for x in signal from
> average=0]
>
> Is just as readable and maintainable as your expanded version, but saves 4
> lines of code. What's not to love?
Be careful about asking questions which you think are rhetorical but
aren't. I can think of at least half a dozen objections to this:
- I'd have no idea what it means without the context of reading
this thread.
- That you call it "MapReduce" while apparently doing something
different from what other people call MapReduce:
https://en.wikipedia.org/wiki/MapReduce
- That it uses = as an expression, and the keyword `from` in a
weird way that doesn't make sense to me.
- The fact that it requires new syntax, so it isn't backwards
compatible. Even if I loved it and your proposal was accepted, I
couldn't use it for at least two years. If I'm writing a library
that has to work with older versions of Python, probably not for
a decade.
- That there's no obvious search terms to google for if you come
across this in code and don't know what it means ("that thing
that looks like a list comprehension but has from in it").
(And yes, before you object, list comps have the same downside.)
- The fact that this uses a functional idiom in the first place,
which many people don't like or get. Especially when they start
getting complex.
If you haven't already already done so, you ought to read the numerous
threads from last month on statement local name bindings:
https://mail.python.org/pipermail/python-ideas/2018-March/thread.html
The barrier to adding new syntax to the language is very high. I suspect
that the *only* chance you have for this sort of comprehension will be
if one of the name binding proposals is accepted. That will give you
*half* of what you want:
[(compute_avg(average, x) as average) for x in signal]
[(average := compute_avg(average, x)) for x in signal]
only needing a way to give it an initial value. Depending on the way
comprehensions work, this might be all you need:
average = 0
smooth_signal [(average := compute_avg(average, x)) for x in signal]
assuming the := syntax is accepted.
An alternative would be to push for a variant of functools.reduce that
yields its values lazily, giving us:
smooth_signal = list(lazy_reduce(compute_avg, x, 0))
--
Steve
More information about the Python-ideas
mailing list