Skip to content

Commit 742a539

Browse files
timholyKeno
authored andcommitted
Rename endof->lastindex and introduce firstindex. Fixes #23354
1 parent ebc5b2c commit 742a539

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+280
-221
lines changed

NEWS.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ New language features
4444
* Values for `Enum`s can now be specified inside of a `begin` block when using the
4545
`@enum` macro ([#25424]).
4646

47+
* `a[begin]` can now be used to address the first element of an integer-indexed collection `a`.
48+
The index is computed by `firstindex(a)` ([#23554]).
49+
4750
Language changes
4851
----------------
4952

@@ -516,7 +519,7 @@ Library improvements
516519
has been changed to `KeySet{K, <:Associative{K}} <: AbstractSet{K}` ([#24580]).
517520

518521
* New function `ncodeunits(s::AbstractString)` gives the number of code units in a string.
519-
The generic definition is constant time but calls `endof(s)` which may be inefficient.
522+
The generic definition is constant time but calls `lastindex(s)` which may be inefficient.
520523
Therefore custom string types may want to define direct `ncodeunits` methods.
521524

522525
* `reverseind(s::AbstractString, i::Integer)` now has an efficient generic fallback, so
@@ -993,6 +996,8 @@ Deprecated or removed
993996

994997
* `scale!` has been deprecated in favor of `mul!`, `mul1!`, and `mul2!` ([#25701]).
995998

999+
* `endof(a)` has been renamed to `lastindex(a)` ([#23554]).
1000+
9961001
* `DateTime()`, `Date()`, and `Time()` have been deprecated, instead use `DateTime(1)`, `Date(1)`
9971002
and `Time(0)` respectively ([#23724]).
9981003

@@ -1152,6 +1157,7 @@ Command-line option changes
11521157
[#23323]: https://github.com/JuliaLang/julia/issues/23323
11531158
[#23341]: https://github.com/JuliaLang/julia/issues/23341
11541159
[#23342]: https://github.com/JuliaLang/julia/issues/23342
1160+
[#23354]: https://github.com/JuliaLang/julia/issues/23354
11551161
[#23366]: https://github.com/JuliaLang/julia/issues/23366
11561162
[#23373]: https://github.com/JuliaLang/julia/issues/23373
11571163
[#23404]: https://github.com/JuliaLang/julia/issues/23404

base/abstractarray.jl

+18-5
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ ndims(::Type{T}) where {T<:AbstractArray} = ndims(supertype(T))
146146
147147
Return the number of elements in the collection.
148148
149-
Use [`endof`](@ref) to get the last valid index of an indexable collection.
149+
Use [`lastindex`](@ref) to get the last valid index of an indexable collection.
150150
151151
# Examples
152152
```jldoctest
@@ -165,17 +165,30 @@ _length(A::AbstractArray) = (@_inline_meta; prod(map(unsafe_length, axes(A)))) #
165165
_length(A) = (@_inline_meta; length(A))
166166

167167
"""
168-
endof(collection) -> Integer
168+
lastindex(collection) -> Integer
169169
170170
Return the last index of the collection.
171171
172172
# Examples
173173
```jldoctest
174-
julia> endof([1,2,4])
174+
julia> lastindex([1,2,4])
175175
3
176176
```
177177
"""
178-
endof(a::AbstractArray) = (@_inline_meta; last(linearindices(a)))
178+
lastindex(a::AbstractArray) = (@_inline_meta; last(linearindices(a)))
179+
180+
"""
181+
firstindex(collection) -> Integer
182+
183+
Return the first index of the collection.
184+
185+
# Examples
186+
```jldoctest
187+
julia> firstindex([1,2,4])
188+
1
189+
```
190+
"""
191+
firstindex(a::AbstractArray) = (@_inline_meta; first(linearindices(a)))
179192

180193
first(a::AbstractArray) = a[first(eachindex(a))]
181194

@@ -204,7 +217,7 @@ end
204217
last(coll)
205218
206219
Get the last element of an ordered collection, if it can be computed in O(1) time. This is
207-
accomplished by calling [`endof`](@ref) to get the last index. Return the end
220+
accomplished by calling [`lastindex`](@ref) to get the last index. Return the end
208221
point of an `AbstractRange` even if it is empty.
209222
210223
# Examples

base/char.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ size(c::Char,d) = convert(Int, d) < 1 ? throw(BoundsError()) : 1
8282
ndims(c::Char) = 0
8383
ndims(::Type{Char}) = 0
8484
length(c::Char) = 1
85-
endof(c::Char) = 1
85+
firstindex(c::Char) = 1
86+
lastindex(c::Char) = 1
8687
getindex(c::Char) = c
8788
getindex(c::Char, i::Integer) = i == 1 ? c : throw(BoundsError())
8889
getindex(c::Char, I::Integer...) = all(x -> x == 1, I) ? c : throw(BoundsError())

base/deprecated.jl

+10-3
Original file line numberDiff line numberDiff line change
@@ -1298,9 +1298,9 @@ end
12981298
@deprecate rsearch(s::AbstractString, r::Regex) findlast(r, s)
12991299
@deprecate rsearch(s::AbstractString, c::Char, i::Integer) findprev(equalto(c), s, i)
13001300
@deprecate rsearch(s::AbstractString, c::Char) findlast(equalto(c), s)
1301-
@deprecate rsearch(a::Union{String,ByteArray}, b::Union{Int8,UInt8}, i::Integer = endof(a)) findprev(equalto(b), a, i)
1302-
@deprecate rsearch(a::String, b::Union{Int8,UInt8}, i::Integer = endof(a)) findprev(equalto(Char(b)), a, i)
1303-
@deprecate rsearch(a::ByteArray, b::Char, i::Integer = endof(a)) findprev(equalto(UInt8(b)), a, i)
1301+
@deprecate rsearch(a::Union{String,ByteArray}, b::Union{Int8,UInt8}, i::Integer = lastindex(a)) findprev(equalto(b), a, i)
1302+
@deprecate rsearch(a::String, b::Union{Int8,UInt8}, i::Integer = lastindex(a)) findprev(equalto(Char(b)), a, i)
1303+
@deprecate rsearch(a::ByteArray, b::Char, i::Integer = lastindex(a)) findprev(equalto(UInt8(b)), a, i)
13041304

13051305
@deprecate searchindex(s::AbstractString, t::AbstractString) first(findfirst(t, s))
13061306
@deprecate searchindex(s::AbstractString, t::AbstractString, i::Integer) first(findnext(t, s, i))
@@ -1385,6 +1385,13 @@ export readandwrite
13851385
@deprecate methodswith(typ, supertypes) methodswith(typ, supertypes = supertypes)
13861386
@deprecate code_lowered(f, types, generated) code_lowered(f, types, generated = generated)
13871387

1388+
# PR 25458
1389+
@deprecate endof(a) lastindex(a)
1390+
function firstindex(a)
1391+
depwarn("if appropriate you should implement `firstindex` for type $(typeof(a)), which might just return 1", :beginof)
1392+
1
1393+
end
1394+
13881395
@deprecate Timer(timeout, repeat) Timer(timeout, interval = repeat)
13891396
@deprecate Timer(callback, delay, repeat) Time(callback, delay, interval = repeat)
13901397
@deprecate names(m, all) names(m, all = all)

base/dict.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function _truncate_at_width_or_chars(str, width, chars="", truncmark="…")
1616

1717
lastidx != 0 && str[lastidx] in chars && (lastidx = prevind(str, lastidx))
1818
truncidx == 0 && (truncidx = lastidx)
19-
if lastidx < endof(str)
19+
if lastidx < lastindex(str)
2020
return String(SubString(str, 1, truncidx) * truncmark)
2121
else
2222
return String(str)

base/essentials.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,8 @@ function length(v::SimpleVector)
525525
@_gc_preserve_end t
526526
return l
527527
end
528-
endof(v::SimpleVector) = length(v)
528+
firstindex(v::SimpleVector) = 1
529+
lastindex(v::SimpleVector) = length(v)
529530
start(v::SimpleVector) = 1
530531
next(v::SimpleVector,i) = (v[i],i+1)
531532
done(v::SimpleVector,i) = (length(v) < i)

base/exports.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -505,14 +505,15 @@ export
505505
allunique,
506506
any!,
507507
any,
508+
firstindex,
508509
collect,
509510
count,
510511
delete!,
511512
deleteat!,
512513
eltype,
513514
empty!,
514515
empty,
515-
endof,
516+
lastindex,
516517
filter!,
517518
filter,
518519
foldl,

base/gmp.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,9 @@ hastypemax(::Type{BigInt}) = false
238238

239239
function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, endpos::Int, base_::Integer, raise::Bool)
240240
# don't make a copy in the common case where we are parsing a whole String
241-
bstr = startpos == start(s) && endpos == endof(s) ? String(s) : String(SubString(s,startpos,endpos))
241+
bstr = startpos == start(s) && endpos == lastindex(s) ? String(s) : String(SubString(s,startpos,endpos))
242242

243-
sgn, base, i = Base.parseint_preamble(true,Int(base_),bstr,start(bstr),endof(bstr))
243+
sgn, base, i = Base.parseint_preamble(true,Int(base_),bstr,start(bstr),lastindex(bstr))
244244
if !(2 <= base <= 62)
245245
raise && throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $base"))
246246
return nothing

base/int.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -539,9 +539,9 @@ end
539539
macro big_str(s)
540540
if '_' in s
541541
# remove _ in s[2:end-1]
542-
bf = IOBuffer(endof(s))
542+
bf = IOBuffer(lastindex(s))
543543
print(bf, s[1])
544-
for c in SubString(s, 2, endof(s)-1)
544+
for c in SubString(s, 2, lastindex(s)-1)
545545
c != '_' && print(bf, c)
546546
end
547547
print(bf, s[end])

base/io.jl

+4-6
Original file line numberDiff line numberDiff line change
@@ -661,15 +661,13 @@ function readuntil(s::IO, delim::T; keep::Bool=false) where T
661661
return out
662662
end
663663

664-
# requires that indices for target are small ordered integers bounded by start and endof
664+
# requires that indices for target are small ordered integers bounded by firstindex and lastindex
665665
# returns whether the delimiter was matched
666666
function readuntil_indexable(io::IO, target#=::Indexable{T}=#, out)
667667
T = eltype(target)
668-
first = start(target)
669-
if done(target, first)
670-
return true
671-
end
672-
len = endof(target)
668+
isempty(target) && return true
669+
first = firstindex(target)
670+
len = lastindex(target)
673671
local cache # will be lazy initialized when needed
674672
second = next(target, first)[2]
675673
max_pos = second

base/markdown/parse/parse.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ config(md::MD) = md.meta[:config]::Config
2323
Base.push!(md::MD, x) = push!(md.content, x)
2424
Base.getindex(md::MD, args...) = md.content[args...]
2525
Base.setindex!(md::MD, args...) = setindex!(md.content, args...)
26-
Base.endof(md::MD) = endof(md.content)
26+
Base.lastindex(md::MD) = lastindex(md.content)
27+
Base.firstindex(md::MD) = firstindex(md.content)
2728
Base.length(md::MD) = length(md.content)
2829
Base.isempty(md::MD) = isempty(md.content)
2930
Base.copy(md::MD) = MD(copy(md.content), copy(md.meta))

base/namedtuple.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ length(t::NamedTuple) = nfields(t)
4848
start(t::NamedTuple) = 1
4949
done(t::NamedTuple, iter) = iter > nfields(t)
5050
next(t::NamedTuple, iter) = (getfield(t, iter), iter + 1)
51-
endof(t::NamedTuple) = nfields(t)
51+
firstindex(t::NamedTuple) = 1
52+
lastindex(t::NamedTuple) = nfields(t)
5253
getindex(t::NamedTuple, i::Int) = getfield(t, i)
5354
getindex(t::NamedTuple, i::Symbol) = getfield(t, i)
5455
indexed_next(t::NamedTuple, i::Int, state) = (getfield(t, i), i+1)

base/number.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ eltype(::Type{T}) where {T<:Number} = T
5252
ndims(x::Number) = 0
5353
ndims(::Type{<:Number}) = 0
5454
length(x::Number) = 1
55-
endof(x::Number) = 1
55+
firstindex(x::Number) = 1
56+
lastindex(x::Number) = 1
5657
IteratorSize(::Type{<:Number}) = HasShape{0}()
5758
keys(::Number) = OneTo(1)
5859

base/pair.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ getindex(p::Pair,i::Int) = getfield(p,i)
5252
getindex(p::Pair,i::Real) = getfield(p, convert(Int, i))
5353
reverse(p::Pair{A,B}) where {A,B} = Pair{B,A}(p.second, p.first)
5454

55-
endof(p::Pair) = 2
55+
firstindex(p::Pair) = 1
56+
lastindex(p::Pair) = 2
5657
length(p::Pair) = 2
5758
first(p::Pair) = p.first
5859
last(p::Pair) = p.second

base/parse.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -209,11 +209,11 @@ or [`nothing`](@ref) if the string does not contain a valid number.
209209
"""
210210
function tryparse(::Type{T}, s::AbstractString; base::Union{Nothing,Integer} = nothing) where {T<:Integer}
211211
# Zero base means, "figure it out"
212-
tryparse_internal(T, s, start(s), endof(s), base===nothing ? 0 : check_valid_base(base), false)
212+
tryparse_internal(T, s, start(s), lastindex(s), base===nothing ? 0 : check_valid_base(base), false)
213213
end
214214

215215
function parse(::Type{T}, s::AbstractString; base::Union{Nothing,Integer} = nothing) where {T<:Integer}
216-
tryparse_internal(T, s, start(s), endof(s), base===nothing ? 0 : check_valid_base(base), true)
216+
tryparse_internal(T, s, start(s), lastindex(s), base===nothing ? 0 : check_valid_base(base), true)
217217
end
218218

219219
## string to float functions ##
@@ -327,7 +327,7 @@ tryparse_internal(T::Type{<:Complex}, s::AbstractString, i::Int, e::Int, raise::
327327

328328
# fallback methods for tryparse_internal
329329
tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos::Int) where T<:Real =
330-
startpos == start(s) && endpos == endof(s) ? tryparse(T, s) : tryparse(T, SubString(s, startpos, endpos))
330+
startpos == start(s) && endpos == lastindex(s) ? tryparse(T, s) : tryparse(T, SubString(s, startpos, endpos))
331331
function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos::Int, raise::Bool) where T<:Real
332332
result = tryparse_internal(T, s, startpos, endpos)
333333
if raise && result === nothing
@@ -339,4 +339,4 @@ tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos::Int, rais
339339
tryparse_internal(T, s, startpos, endpos, 10, raise)
340340

341341
parse(::Type{T}, s::AbstractString) where T<:Union{Real,Complex} =
342-
tryparse_internal(T, s, start(s), endof(s), true)
342+
tryparse_internal(T, s, start(s), lastindex(s), true)

base/precompile.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -545,11 +545,11 @@ precompile(Tuple{Type{BoundsError}, Array{Expr, 1}, Base.UnitRange{Int64}})
545545
precompile(Tuple{getfield(Base.Cartesian, Symbol("#@ncall")), Int64, Symbol, Symbol})
546546
precompile(Tuple{typeof(Base.getindex), Tuple{Symbol}, Base.UnitRange{Int64}})
547547
precompile(Tuple{getfield(Base.Cartesian, Symbol("#@ncall")), Int64, Symbol, Symbol, Expr})
548-
precompile(Tuple{typeof(Base.endof), Tuple{Symbol, Expr}})
548+
precompile(Tuple{typeof(Base.lastindex), Tuple{Symbol, Expr}})
549549
precompile(Tuple{typeof(Base.getindex), Tuple{Symbol, Expr}, Base.UnitRange{Int64}})
550550
precompile(Tuple{getfield(Base.Cartesian, Symbol("#@nloops")), Int64, Symbol, Expr, Expr})
551-
precompile(Tuple{typeof(Base.endof), Tuple{Expr}})
552-
precompile(Tuple{typeof(Base.endof), Tuple{Symbol, Symbol, Symbol}})
551+
precompile(Tuple{typeof(Base.lastindex), Tuple{Expr}})
552+
precompile(Tuple{typeof(Base.lastindex), Tuple{Symbol, Symbol, Symbol}})
553553
precompile(Tuple{typeof(Base.getindex), Tuple{Symbol, Symbol, Symbol}, Base.UnitRange{Int64}})
554554
precompile(Tuple{Type{Expr}, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol})
555555
precompile(Tuple{typeof(Base.join), Base.GenericIOBuffer{Array{UInt8, 1}}, Tuple{String, String}, Char})
@@ -752,7 +752,7 @@ precompile(Tuple{typeof(Base.Markdown.terminline), Base.GenericIOBuffer{Array{UI
752752
precompile(Tuple{typeof(Base._search), Base.SubString{String}, String, Int64})
753753
precompile(Tuple{typeof(Base._split), Base.SubString{String}, String, Int64, Bool, Array{Base.SubString{String}, 1}})
754754
precompile(Tuple{getfield(Base.Markdown, Symbol("#kw##wrapped_lines")), Array{Any, 1}, typeof(Base.Markdown.wrapped_lines), Base.SubString{String}})
755-
precompile(Tuple{typeof(Base.endof), Array{AbstractString, 1}})
755+
precompile(Tuple{typeof(Base.lastindex), Array{AbstractString, 1}})
756756
precompile(Tuple{typeof(Base.getindex), Array{AbstractString, 1}, Base.UnitRange{Int64}})
757757
precompile(Tuple{typeof(Base.throw_boundserror), Array{AbstractString, 1}, Tuple{Base.UnitRange{Int64}}})
758758
precompile(Tuple{typeof(Base.unsafe_copyto!), Array{AbstractString, 1}, Int64, Array{AbstractString, 1}, Int64, Int64})

base/printf.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ function parse(s::AbstractString)
5353
j1 = j
5454
j = k
5555
end
56-
i > endof(s) || push!(list, s[i:end])
56+
i > lastindex(s) || push!(list, s[i:end])
5757
# coalesce adjacent strings
5858
i = 1
5959
while i < length(list)

base/process.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,7 @@ wait(x::ProcessChain) = for p in x.processes; wait(p); end
820820
show(io::IO, p::Process) = print(io, "Process(", p.cmd, ", ", process_status(p), ")")
821821

822822
# allow the elements of the Cmd to be accessed as an array or iterator
823-
for f in (:length, :endof, :start, :keys, :first, :last)
823+
for f in (:length, :firstindex, :lastindex, :start, :keys, :first, :last)
824824
@eval $f(cmd::Cmd) = $f(cmd.exec)
825825
end
826826
eltype(::Type{Cmd}) = eltype(fieldtype(Cmd, :exec))

base/reduce.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ end
126126
Like [`mapreduce`](@ref), but with guaranteed right associativity, as in [`foldr`](@ref).
127127
`v0` will be used exactly once.
128128
"""
129-
mapfoldr(f, op, v0, itr) = mapfoldr_impl(f, op, v0, itr, endof(itr))
129+
mapfoldr(f, op, v0, itr) = mapfoldr_impl(f, op, v0, itr, lastindex(itr))
130130

131131
"""
132132
mapfoldr(f, op, itr)
@@ -137,7 +137,7 @@ Specifically, `mapfoldr(f, op, itr)` produces the same result as
137137
In general, this cannot be used with empty collections (see [`reduce(op, itr)`](@ref)).
138138
"""
139139
function mapfoldr(f, op, itr)
140-
i = endof(itr)
140+
i = lastindex(itr)
141141
if isempty(itr)
142142
return Base.mapreduce_empty_iter(f, op, itr, IteratorEltype(itr))
143143
end

base/regex.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ matchall(re::Regex, str::SubString; overlap::Bool = false) =
267267

268268
# TODO: return only start index and update deprecation
269269
function findnext(re::Regex, str::Union{String,SubString}, idx::Integer)
270-
if idx > nextind(str,endof(str))
270+
if idx > nextind(str,lastindex(str))
271271
throw(BoundsError())
272272
end
273273
opts = re.match_options
@@ -315,7 +315,7 @@ function _replace(io, repl_s::SubstitutionString, str, r, re)
315315
RBRACKET = '>'
316316
repl = repl_s.string
317317
i = start(repl)
318-
e = endof(repl)
318+
e = lastindex(repl)
319319
while i <= e
320320
if repl[i] == SUB_CHAR
321321
next_i = nextind(repl, i)
@@ -393,7 +393,7 @@ function next(itr::RegexMatchIterator, prev_match)
393393
offset = prev_match.offset
394394
end
395395
else
396-
offset = prev_match.offset + endof(prev_match.match)
396+
offset = prev_match.offset + lastindex(prev_match.match)
397397
end
398398

399399
opts_nonempty = UInt32(PCRE.ANCHORED | PCRE.NOTEMPTY_ATSTART)

0 commit comments

Comments
 (0)