Skip to content

Commit

Permalink
make last work on any reversible collection (JuliaLang#42991)
Browse files Browse the repository at this point in the history
  • Loading branch information
MasonProtter authored and LilithHafner committed Feb 22, 2022
1 parent 83cd5c3 commit ba8a3b9
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 4 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ Language changes
* `@time` and `@timev` now take an optional description to allow annotating the source of time reports.
i.e. `@time "Evaluating foo" foo()` ([#42431])
* New `@showtime` macro to show both the line being evaluated and the `@time` report ([#42431])
* `last(collection)` will now work on any collection that supports `Iterators.reverse` and `first`, rather than being
restricted to indexable collections.

Compiler/Runtime improvements
-----------------------------
Expand Down
11 changes: 8 additions & 3 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -462,11 +462,15 @@ end
last(coll)
Get the last element of an ordered collection, if it can be computed in O(1) time. This is
accomplished by calling [`lastindex`](@ref) to get the last index. Return the end
point of an [`AbstractRange`](@ref) even if it is empty.
accomplished by calling [`Iterators.reverse`](@ref) and then [`first`](@ref) on that reversed iterator.
Return the end point of an [`AbstractRange`](@ref) even if it is empty.
See also [`first`](@ref), [`endswith`](@ref).
!!! compat "Julia 1.8"
For versions of julia older than 1.8, `last(x)` will only work on collections that support indexing and
[`lastindex`](@ref).
# Examples
```jldoctest
julia> last(1:2:10)
Expand All @@ -476,7 +480,8 @@ julia> last([1; 2; 3; 4])
4
```
"""
last(a) = a[end]
last(a) = first(Iterators.reverse(a))
last(a::AbstractVector) = a[end]

"""
last(itr, n::Integer)
Expand Down
1 change: 0 additions & 1 deletion base/iterators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ size(r::Reverse) = size(r.itr)
IteratorSize(::Type{Reverse{T}}) where {T} = IteratorSize(T)
IteratorEltype(::Type{Reverse{T}}) where {T} = IteratorEltype(T)
last(r::Reverse) = first(r.itr) # the first shall be last
first(r::Reverse) = last(r.itr) # and the last shall be first

# reverse-order array iterators: assumes more-specialized Reverse for eachindex
@propagate_inbounds function iterate(A::Reverse{<:AbstractArray}, state=(reverse(eachindex(A.itr)),))
Expand Down
5 changes: 5 additions & 0 deletions test/iterators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -885,3 +885,8 @@ end
@test Iterators.peel(x^2 for x in 2:4)[1] == 4
@test Iterators.peel(x^2 for x in 2:4)[2] |> collect == [9, 16]
end

@testset "last for iterators" begin
@test last(Iterators.map(identity, 1:3)) == 3
@test last(Iterators.filter(iseven, (Iterators.map(identity, 1:3)))) == 2
end

0 comments on commit ba8a3b9

Please sign in to comment.