# Equivalent of `last` for iterators

While responding to a different topic, I needed the last element of an iterator. This has at least one fairly simple and efficient solution which has appeared elsewhere:

``````itrlast(itr) = foldl((_,y)->y,itr)
``````

but `last` can also return several elements from the end of a collection, so here is a suggested function to achieve this generally:

``````using CircularArrays
using IterTools

function itrlast(itr, n::Integer)
n > 0 || error("Must keep at least one element")
pi = peekiter(itr)
e = peek(pi)
isnothing(e) && "Iterator is empty"
T = eltype(something(e))
buf, i = foldl(((buf,i),e)->(buf[i+1] = e; (buf,i+1)),pi;
init=(CircularArray(Vector{T}(undef,n)),0))
i<n && error("Iterator has less than \$n elements")
@view buf[i-n+1:i]
end
``````

With this method defined, the following works:

``````julia> itrlast(1:10,2)
2-element view(CircularVector(::Vector{Int64}), 9:10) with eltype Int64:
9
10
``````

and also:

``````julia> itrlast(Iterators.take(iterated(x->√(6+x),1.0),23),5)
5-element view(CircularVector(::Vector{Float64}), 19:23) with eltype Float64:
2.9999999999999787
2.9999999999999964
2.9999999999999996
3.0
3.0
``````

This function, and perhaps `last` as well, can be generalized to “index” any iterator with an index range (e.g. 1:3:10 or ?? last(1:3:end, 5) of an itr ??).

The most efficient thing is to `first(Iterators.reverse(itr))`. This works for any iterator that supports the reverse iteration interface (many but not all iterators). There was a PR to make this the default behavior for `last` (julia#42991), but it was reverted as being too breaking.
Of course, many iterators that support reverse iteration also implement `last`.
This is fine, but the reason that `last` doesn’t do this kind of thing in general is that it is documented as being O(1).