Skip to content

Commit 1f484c3

Browse files
authored
make last work on any reversible collection (#42991)
1 parent dba8f03 commit 1f484c3

File tree

4 files changed

+15
-4
lines changed

4 files changed

+15
-4
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ Language changes
2525
* `@time` and `@timev` now take an optional description to allow annotating the source of time reports.
2626
i.e. `@time "Evaluating foo" foo()` ([#42431])
2727
* New `@showtime` macro to show both the line being evaluated and the `@time` report ([#42431])
28+
* `last(collection)` will now work on any collection that supports `Iterators.reverse` and `first`, rather than being
29+
restricted to indexable collections.
2830

2931
Compiler/Runtime improvements
3032
-----------------------------

base/abstractarray.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -462,11 +462,15 @@ end
462462
last(coll)
463463
464464
Get the last element of an ordered collection, if it can be computed in O(1) time. This is
465-
accomplished by calling [`lastindex`](@ref) to get the last index. Return the end
466-
point of an [`AbstractRange`](@ref) even if it is empty.
465+
accomplished by calling [`Iterators.reverse`](@ref) and then [`first`](@ref) on that reversed iterator.
466+
Return the end point of an [`AbstractRange`](@ref) even if it is empty.
467467
468468
See also [`first`](@ref), [`endswith`](@ref).
469469
470+
!!! compat "Julia 1.8"
471+
For versions of julia older than 1.8, `last(x)` will only work on collections that support indexing and
472+
[`lastindex`](@ref).
473+
470474
# Examples
471475
```jldoctest
472476
julia> last(1:2:10)
@@ -476,7 +480,8 @@ julia> last([1; 2; 3; 4])
476480
4
477481
```
478482
"""
479-
last(a) = a[end]
483+
last(a) = first(Iterators.reverse(a))
484+
last(a::AbstractVector) = a[end]
480485

481486
"""
482487
last(itr, n::Integer)

base/iterators.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ size(r::Reverse) = size(r.itr)
103103
IteratorSize(::Type{Reverse{T}}) where {T} = IteratorSize(T)
104104
IteratorEltype(::Type{Reverse{T}}) where {T} = IteratorEltype(T)
105105
last(r::Reverse) = first(r.itr) # the first shall be last
106-
first(r::Reverse) = last(r.itr) # and the last shall be first
107106

108107
# reverse-order array iterators: assumes more-specialized Reverse for eachindex
109108
@propagate_inbounds function iterate(A::Reverse{<:AbstractArray}, state=(reverse(eachindex(A.itr)),))

test/iterators.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,3 +885,8 @@ end
885885
@test Iterators.peel(x^2 for x in 2:4)[1] == 4
886886
@test Iterators.peel(x^2 for x in 2:4)[2] |> collect == [9, 16]
887887
end
888+
889+
@testset "last for iterators" begin
890+
@test last(Iterators.map(identity, 1:3)) == 3
891+
@test last(Iterators.filter(iseven, (Iterators.map(identity, 1:3)))) == 2
892+
end

0 commit comments

Comments
 (0)