What is `last(inf_iter)`. E.g `last(count())`.

To me, the obvious spelling is:

    for last in it: pass
    doSomething(last)

This makes it clear that is the users job to make sure `it` terminates.
There's no general way to get the last item without looking through all the
earlier ones.

On Oct 23, 2016 7:58 AM, "Danilo J. S. Bellini" <danilo.bell...@gmail.com>
wrote:

> The idea is to let generator expressions and list/set comprehensions have
> a clean syntax to access its last output. That would allow them to be an
> alternative syntax to the scan higher-order function [1] (today implemented
> in the itertools.accumulate function), which leads to an alternative way
> to write a fold/reduce. It would be nice to have something like:
>
> >>> last(abs(prev - x) for x in [3, 4, 5] from prev = 2)
> 2
>
> instead of a reduce:
>
> >>> from functools import reduce
> >>> reduce(lambda prev, x: abs(prev - x), [3, 4, 5], 2)
> 2
>
> or an imperative approach:
>
> >>> prev = 2
> >>> for x in [3, 4, 5]:
> ...     prev = abs(prev - x)
> >>> prev
> 2
>
> or getting the last from accumulate:
>
> >>> from itertools import accumulate
> >>> list(accumulate([2, 3, 4, 5], lambda prev, x: abs(prev - x)))[-1]
> 2
>
> or...
>
> >>> [prev for prev in [2]
> ...       for x in [3, 4, 5]
> ...       for prev in [abs(prev - x)]
> ... ][-1]
> 2
>
> Actually, I already wrote a solution for something similar to that:
> PyScanPrev [2]. I'm using bytecode manipulation to modify the generator
> expression and set/list comprehensions semantics to create a "scan", but
> it has the limitation of using only code with a valid syntax as the input,
> so I can't use "from" inside a generator expression / list comprehension.
> The solution was to put the first output into the iterable and define the
> "prev" name elsewhere:
>
> >>> last(abs(prev - x) for x in [2, 3, 4, 5])
> 2
>
> That line works with PyScanPrev (on Python 3.4 and 3.5) when defined in a
> function with a @enable_scan("prev") decorator. That was enough to create
> a "test suite" of doctest-based examples that shows several scan use cases
> [2].
>
> This discussion started in a Brazilian list when someone asked how she
> could solve a simple uppercase/lowercase problem [3]. The goal was to
> alternate the upper/lower case of a string while neglecting the chars that
> doesn't apply (i.e., to "keep the state" when the char isn't a letter). After
> the discussion, I wrote the PyScanPrev package, and recently I've added
> this historical "alternate" function as the "conditional toggling"
> example [4].
>
> Then I ask, can Python include that "scan" access to the last output in
> its list/set/dict comprehension and generator expression syntax? There are
> several possible applications for the scan itself as well as for the
> fold/reduce (signal processing, control theory, physics, economics, etc.),
> some of them I included as PyScanPrev examples. Some friends (people who
> like control engineering and/or signal processing) liked the "State-space
> model" example, where I included a "leaking bucket-spring-damper"
> simulation using the scan-enabled generator expressions [5].
>
> About the syntax, there are several ideas on how that can be written.
> Given a "prev" identifier, a "target" identifier, an input "iterable" and
> an optional "start" value (and perhaps an optional "echo_start", which I
> assume True by default), some of them are:
>
> [func(prev, target) for target in iterable from prev = start]
> [func(prev, target) for target in iterable] -> prev = start
> [func(prev, target) for target in iterable] -> prev as start
> [func(prev, target) for target in iterable] from prev = start
> [func(prev, target) for target in iterable] from prev as start
> [func(prev, target) for target in iterable] with prev as start
> prev = start -> [func(prev, target) for target in iterable]
> prev(start) -> [func(prev, target) for target in iterable]
> [func(prev, target) for prev -> target in start -> iterable]
> [prev = start -> func(prev, target) for target in iterable]
>
> # With ``start`` being the first value of the iterable, i.e.,
> #   iterable = prepend(start, data)
> [func(prev, target) for target in iterable from prev]
> [func(prev, target) for target in iterable] -> prev
> [func(prev, target) for target in iterable] from prev
> prev -> [func(prev, target) for target in iterable]
>
> Before writing PyScanPrev, in [6] (Brazilian Portuguese) I used stackfull
> [7] to implement that idea, an accumulator example using that library is:
>
> >>> from stackfull import push, pop, stack
> >>> [push(pop() + el if stack() else el) for el in range(5)]
> [0, 1, 3, 6, 10]
> >>> list(itertools.accumulate(range(5)))
> [0, 1, 3, 6, 10]
>
> There are more I can say (e.g. the pyscanprev.scan function has a "start"
> value and an "echo_start" keyword argument, resources I missed in
> itertools.accumulate) but the links below already have a lot of information.
>
> [1] https://en.wikipedia.org/wiki/Prefix_sum#Scan_higher_order_function
> [2] https://pypi.python.org/pypi/pyscanprev
> [3] https://groups.google.com/forum/#!topic/grupy-sp/wTIj6G5_5S0
> [4] https://github.com/danilobellini/pyscanprev/blob/
> v0.1.0/examples/conditional-toggling.rst
> [5] https://github.com/danilobellini/pyscanprev/blob/
> v0.1.0/examples/state-space.rst
> [6] https://groups.google.com/forum/#!topic/grupy-sp/UZp-lVSWK1s
> [7] https://pypi.python.org/pypi/stackfull
>
> --
> 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/
>
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to