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

Wes Turner wes.turner at gmail.com
Sun Nov 6 20:27:35 EST 2016


- So, IIUC, for recursive list comprehensions
  - "prev" = x_(n-1)
  - there is a need to define an initial value
    - chain([1000], [...])
  - sometimes, we actually need window function
    - __[0] = x_(n-1)
    - __[1] = x_(n-2)  # this
    - __[-1] = x_(n-2)  # or this
    - this can be accomplished with dequeue
      - __= dequeue([1000], maxlen)
    - for recursive list comprehensions, we'd want to bind e.g. __ to a
dequeue

[f(__[0], x) for x in y with __ = dequeue((1000,), 1)]

But the proposed syntax differs from this interpretation:

- "from bal = 1000" # ~= with prev = dequeue((1000,), 1)[-1]

(Recursive) fibonacci would then require a dequeue (..., 2)

Other than brevity, is there any advantage to list comprehensions over a
for loop?
- IIRC,  reduce() and fold() can avoid unnecessary variable binding, but
require lower-level debugging.

A recursive list comprehension syntax would be cool. Is there a better
variable name than '__'?

On Sunday, November 6, 2016, Danilo J. S. Bellini <danilo.bellini at gmail.com>
wrote:

> 2016-11-06 18:00 GMT-02:00 Stephen J. Turnbull <turnbull.stephen.fw at u.
> tsukuba.ac.jp
> <javascript:_e(%7B%7D,'cvml','turnbull.stephen.fw at u.tsukuba.ac.jp');>>:
>
>> Danilo J. S. Bellini writes:
>>
>>  > About the effort, do you really find the examples below with the new
>>  > proposed syntax difficult to understand?
>>
>> No.  I just don't see how they would become tools I would use.  My main
>> interest here was in your claim to have economic applications, but the
>> examples you give don't seem to offer big wins for the kind of
>> calculations I, my students, or my colleagues do.  Perhaps you will
>> have better luck interesting/persuading others.
>>
>
> If you want something simple, the itertools.accumulate examples from
> docs.python.org include a simple "loan amortization" example:
>
> >>> # Amortize a 5% loan of 1000 with 4 annual payments of 90
> >>> cashflows = [1000, -90, -90, -90, -90]
> >>> list(accumulate(cashflows, lambda bal, pmt: bal*1.05 + pmt))
> [1000, 960.0, 918.0, 873.9000000000001, 827.5950000000001]
>
> >>> # With the proposed syntax
> >>> payments = [90, 90, 90, 90]
> >>> [bal * 1.05 - pmt for pmt in payments from bal = 1000]
> [1000, 960.0, 918.0, 873.9000000000001, 827.5950000000001]
>
>
> From the Wilson J. Rugh "Linear Systems Theory" book, chapter 20 "Discrete
> Time State Equations", p. 384-385 (the very first example on the topic):
>
> """
> A simple, classical model in economics for national income y(k) in year k
> describes y(k) in terms of consumer expenditure c(k), private investment
> i(k), and government expenditure g(k) according to:
>
> y(k) = c(k) + i(k) + g(k)
>
> These quantities are interrelated by the following assumptions. First,
> consumer expenditure in year k+1 is proportional to the national income in
> year k,
>
> c(k+1) = α·y(k)
>
> where the constant α is called, impressively enough, the marginal
> propensity to consume. Second, the private investment in year k+1 is
> proportional to the increase in consumer expenditure from year k to year
> k+1,
>
> i(k+1) = β·[c(k+1) - c(k)]
>
> where the constant β is a growth coefficient. Typically 0 < α < 1 and β >
> 0.
>
> From these assumptions we can write the two scalar difference equations
>
> c(k+1) = α·c(k) + α·i(k) + α·g(k)
> i(k+1) = (β·α-β)·c(k) + β·α·i(k) + β·α·g(k)
>
> Defining state variables as x₁(k) = c(k) and x₂(k) = i(k), the output as
> y(k), and the input as g(k), we obtain the linear state equation
>
> #          ⎡   α      α ⎤        ⎡ α ⎤
> # x(k+1) = ⎢            ⎥·x(k) + ⎢   ⎥·g(k)
> #          ⎣β·(α-1)  β·α⎦        ⎣β·α⎦
> #
> #   y(k) = [1  1]·x(k) + g(k)
>
> Numbering the years by k = 0, 1, ..., the initial state is provided by
> c(0) and i(0).
> """
>
> You can use my "ltiss" or "ltvss" (if alpha/beta are time varying)
> functions from the PyScanPrev state-space example to simulate that, or some
> dedicated function. The linear time varying version with the proposed
> syntax would be (assuming alpha, beta and g are sequences like
> lists/tuples):
>
> >>> from numpy import mat
> >>> def first_digital_linear_system_example_in_book(alpha, beta, c0, i0,
> g):
> ...     A = (mat([[a,       a  ],
> ...               [b*(a-1), b*a]]) for a, b in zip(alpha, beta))
> ...     B = (mat([[a  ],
> ...               [b*a]]) for a, b in zip(alpha, beta))
> ...     x0 = mat([[c0],
> ...               [i0]])
> ...     x = (Ak*xk + Bk*gk for Ak, Bk, gk in zip(A, B, g) from xk = x0)
> ...     return [xk.sum() + gk for xk, gk in zip(x, g)]
>
> If A and B were constants, it's simpler, as the scan line would be:
>
> x = (A*xk + B*gk for gk in g from xk = x0)
>
> --
> 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...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20161106/2cd26bab/attachment-0001.html>


More information about the Python-ideas mailing list