- 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@gmail.com> wrote:
2016-11-06 18:00 GMT-02:00 Stephen J. Turnbull <turnbull.stephen.fw@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]


>>> # W
ith 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)