diff --git a/NEWS.md b/NEWS.md index 0ea9fc42d2c33..9223278bead5d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -997,7 +997,9 @@ Deprecated or removed * `scale!` has been deprecated in favor of `mul!`, `mul1!`, and `mul2!` ([#25701]). - * `endof(a)` has been renamed to `lastindex(a)` ([#23554]). + * `endof(a)` has been renamed to `lastindex(a)`, and the `end` keyword in indexing expressions now + lowers to either `lastindex(a)` (in the case with only one index) or `lastindex(a, d)` (in cases + where there is more than one index and `end` appears at dimension `d`) ([#23554], [#25763]). * `DateTime()`, `Date()`, and `Time()` have been deprecated, instead use `DateTime(1)`, `Date(1)` and `Time(0)` respectively ([#23724]). diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 9eb87fee2647c..27b85da2ba564 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -176,6 +176,7 @@ julia> lastindex([1,2,4]) ``` """ lastindex(a::AbstractArray) = (@_inline_meta; last(linearindices(a))) +lastindex(a::AbstractArray, n) = (@_inline_meta; last(axes(a, n))) """ firstindex(collection) -> Integer @@ -189,6 +190,7 @@ julia> firstindex([1,2,4]) ``` """ firstindex(a::AbstractArray) = (@_inline_meta; first(linearindices(a))) +firstindex(a::AbstractArray, n) = (@_inline_meta; first(axes(a, n))) first(a::AbstractArray) = a[first(eachindex(a))] diff --git a/base/deprecated.jl b/base/deprecated.jl index badec0251adab..8940e23ca9904 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1392,6 +1392,12 @@ function firstindex(a) 1 end +# PR 25763 +function lastindex(a, n) + depwarn("if appropriate you should implement `lastindex(a, n)` for type $(typeof(a))`, which might just return `last(axes(a, n))`", :lastindex) + last(axes(a, n)) +end + @deprecate Timer(timeout, repeat) Timer(timeout, interval = repeat) @deprecate Timer(callback, delay, repeat) Time(callback, delay, interval = repeat) @deprecate names(m, all) names(m, all = all) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index aef2a8485da17..25740675aa348 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -90,16 +90,16 @@ ;; the array `a` in the `n`th index. ;; `tuples` are a list of the splatted arguments that precede index `n` ;; `last` = is this last index? -;; returns a call to lastindex(a) or last(axes(a,n)) +;; returns a call to lastindex(a) or lastindex(a,n) (define (end-val a n tuples last) (if (null? tuples) (if (and last (= n 1)) `(call (top lastindex) ,a) - `(call (top last) (call (top axes) ,a ,n))) + `(call (top lastindex) ,a ,n)) (let ((dimno `(call (top +) ,(- n (length tuples)) ,.(map (lambda (t) `(call (top length) ,t)) tuples)))) - `(call (top last) (call (top axes) ,a ,dimno))))) + `(call (top lastindex) ,a ,dimno)))) ;; replace `end` for the closest ref expression, so doesn't go inside nested refs (define (replace-end ex a n tuples last) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 19d84867a1bc8..f66b4c94d44c7 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -453,7 +453,16 @@ function test_primitives(::Type{T}, shape, ::Type{TestAbstractArray}) where T B = T(A) # last(a) - @test last(B) == B[length(B)] + @test last(B) == B[lastindex(B)] == B[end] == A[end] + @test lastindex(B) == lastindex(A) == last(linearindices(B)) + @test lastindex(B, 1) == lastindex(A, 1) == last(axes(B, 1)) + @test lastindex(B, 2) == lastindex(A, 2) == last(axes(B, 2)) + + # first(a) + @test first(B) == B[firstindex(B)] == B[1] == A[1] # TODO: use B[begin] once parser transforms it + @test firstindex(B) == firstindex(A) == first(linearindices(B)) + @test firstindex(B, 1) == firstindex(A, 1) == first(axes(B, 1)) + @test firstindex(B, 2) == firstindex(A, 2) == first(axes(B, 2)) # isassigned(a::AbstractArray, i::Int...) j = rand(1:length(B)) diff --git a/test/offsetarray.jl b/test/offsetarray.jl index 631bfee14c5aa..de21878a1cf72 100644 --- a/test/offsetarray.jl +++ b/test/offsetarray.jl @@ -328,6 +328,9 @@ cv = copy(v) @test reverse!(cv) == rv A = OffsetArray(rand(4,4), (-3,5)) +@test lastindex(A) == 16 +@test lastindex(A, 1) == 1 +@test lastindex(A, 2) == 9 @test A ≈ A @test axes(A') === (6:9, -2:1) @test parent(copy(A')) == copy(parent(A)')