Sure, a better last() should try to index into it[-1] first as an efficiency. And there are lots of iterators where the last element is predictable without looking through all the prior items. I know the last item of itertools.repeat(7, sys.maxsize) without having to loop for hours.

But the general case is that you need to get all the head elements to determine last().

If the main idea is "to access the previous iteration" then we already have it retools.accumulate() for exactly that purpose. If you want something that bandages a little different from accumulate, writing generator functions us really easy.


On Oct 23, 2016 8:59 AM, "Danilo J. S. Bellini" <danilo.bellini@gmail.com> wrote:

Of course. But if you want last(), why not just spell the utility function as I did? [...]

I'm not against a general "last", I just said the main idea of this thread is the access to the previous iteration output in a list/set/dict comprehension or generator expression.

Actually, your code is similar to the reference implementation I wrote for PyScanPrev, the main difference is that my "last" raises a StopIteration on an empty input instead of an UnboundLocalError:
https://github.com/danilobellini/pyscanprev/blob/v0.1.0/pyscanprev.py#L148
When the input is a sequence, it should be optimized to get the item at the index -1.

That works fine for any iteratable (including a list, array, etc), whether or not it's a reduction/accumulation.

Lists and arrays don't need to be traversed.

Consuming the iterator is *necessary* to get the last item. There's no way around that.

Not if there's enough information to create the last value. Perhaps on the it = iter(range(9999999)) one can get 2 values (call next(it) twice) and use its __length_hint__ to create the last value. But I think only sequences should have such an optimization, not iterators.

--
Danilo J. S. Bellini
---------------
"It is not our business to set up prohibitions, but to arrive at conventions." (R. Carnap)