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 from average=0.] We could use given for both the in-loop variable update and the variable initialization: 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) Becomes: (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 "given" keyword. 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 [0] 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.bell...@gmail.com> wrote: > On 16 April 2018 at 10:49, Peter O'Connor <peter.ed.ocon...@gmail.com> > wrote: > >> 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: > https://github.com/danilobellini/pyscanprev/blob/ > master/examples/iir-filter.rst > > I tried: >> >> @enable_scan("average") >> def exponential_moving_average_pyscan(signal, decay, initial=0): >> yield from ((1-decay)*(average or initial) + decay*x for x in >> signal) >> >> >> smooth_signal_9 = list(exponential_moving_average_pyscan(signal, >> decay=decay))[1:] >> >> 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" > value? > > 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, > signal)) > ... > >>> 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) >
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/