[Python-ideas] Proposal: A Reduce-Map Comprehension and a "last" builtin
peter.ed.oconnor at gmail.com
Thu May 24 08:06:03 EDT 2018
To give this old horse a kick: The "given" syntax in the recent thread
could give a nice solution for the problem that started this thread.
Instead of my proposal of:
smooth_signal = [average := (1-decay)*average + decay*x for x in signal
We could use given for both the in-loop variable update and the variable
smooth_signal = [average given average=(1-decay)*average + decay*x for
x in signal] given average=0.
This especially makes sense for the extended syntax, where my proposal of:
(z, y := f(z, x) -> y for x in iter_x from z=initial_z)
(y given z, y = f(z, x) for x in iter_x) given z=initial_z
So in stead of adding 2 symbols and a keyword, we just need to add the one
It's worth noting, as Serhiy pointed out, that this is already supported in
python, albeit with a very clunky syntax:
smooth_signal = [average for average in  for x in signal for average
in [(1-decay)*average + decay*x]]
(y for z in [initial_z] for x in iter_x for z, y in [f(z, x)])
On Tue, Apr 17, 2018 at 12:02 AM, Danilo J. S. Bellini <
danilo.bellini at gmail.com> wrote:
> On 16 April 2018 at 10:49, Peter O'Connor <peter.ed.oconnor at gmail.com>
>> Are you able to show how you'd implement the moving average example with
>> your package?
> Sure! The single pole IIR filter you've shown is implemented here:
> I tried:
>> def exponential_moving_average_pyscan(signal, decay, initial=0):
>> yield from ((1-decay)*(average or initial) + decay*x for x in
>> smooth_signal_9 = list(exponential_moving_average_pyscan(signal,
>> Which almost gave the right result, but seemed to get the initial
>> conditions wrong.
> I'm not sure what you were expecting. A sentinel as the first "average"
> Before the loop begins, this scan-generator just echoes the first input,
> like itertools.accumulate.
> That is, the first value this generator yields is the first "signal"
> value, which is then the first "average" value.
> To put an initial memory state, you should do something like this (I've
> removed the floating point trailing noise):
> >>> from pyscanprev import enable_scan, prepend
> >>> @enable_scan("y")
> >>> def iir_filter(signal, decay, memory=0):
> ... return ((1 - decay) * y + decay * x for x in prepend(memory,
> >>> list(iir_filter([1, 2, 3, 2, 1, -1, -2], decay=.1, memory=5))
> [5, 4.6, 4.34, 4.206, 3.9854, 3.68686, 3.218174, 2.6963566]
> In that example, "y" is the "previous result" (a.k.a. accumulator, or
> what had been called "average" here).
> Danilo J. S. Bellini
> "*It is not our business to set up prohibitions, but to arrive at
> conventions.*" (R. Carnap)
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Python-ideas