Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change sentinel in find(first|next|prev|last) to nothing #25472

Merged
merged 2 commits into from
Jan 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1495,7 +1495,7 @@ cat(n::Integer, x::Integer...) = reshape([x...], (ntuple(x->1, n-1)..., length(x
"""
findnext(A, i::Integer)

Find the next linear index >= `i` of a `true` element of `A`, or `0` if not found.
Find the next linear index >= `i` of a `true` element of `A`, or `nothing` if not found.

# Examples
```jldoctest
Expand All @@ -1508,7 +1508,6 @@ julia> findnext(A, 1)
2

julia> findnext(A, 3)
0
```
"""
function findnext(A, start::Integer)
Expand All @@ -1526,14 +1525,14 @@ function findnext(A, start::Integer)
end
i = nextind(A, i)
end
return 0
return nothing
end

"""
findfirst(A)

Return the linear index of the first `true` value in `A`.
Return `0` if no such value is found.
Return `nothing` if no such value is found.
To search for other kinds of values, pass a predicate as the first argument.

# Examples
Expand All @@ -1546,16 +1545,17 @@ julia> A = [false false; true false]
julia> findfirst(A)
2

julia> findfirst(falses(3))
0
julia> findfirst(falses(3)) == nothing
true
```
"""
findfirst(A) = findnext(A, 1)

"""
findnext(predicate::Function, A, i::Integer)

Find the next linear index >= `i` of an element of `A` for which `predicate` returns `true`, or `0` if not found.
Find the next linear index >= `i` of an element of `A` for which `predicate` returns `true`,
or `nothing` if not found.

# Examples
```jldoctest
Expand All @@ -1567,8 +1567,8 @@ julia> A = [1 4; 2 2]
julia> findnext(isodd, A, 1)
1

julia> findnext(isodd, A, 2)
0
julia> findnext(isodd, A, 2) == nothing
true
```
"""
function findnext(testf::Function, A, start::Integer)
Expand All @@ -1580,14 +1580,14 @@ function findnext(testf::Function, A, start::Integer)
end
i = nextind(A, i)
end
return 0
return nothing
end

"""
findfirst(predicate::Function, A)

Return the linear index of the first element of `A` for which `predicate` returns `true`.
Return `0` if there is no such element.
Return `nothing` if there is no such element.

# Examples
```jldoctest
Expand All @@ -1599,8 +1599,8 @@ julia> A = [1 4; 2 2]
julia> findfirst(iseven, A)
2

julia> findfirst(x -> x>10, A)
0
julia> findfirst(x -> x>10, A) == nothing
true

julia> findfirst(equalto(4), A)
3
Expand All @@ -1611,7 +1611,7 @@ findfirst(testf::Function, A) = findnext(testf, A, 1)
"""
findprev(A, i::Integer)

Find the previous linear index <= `i` of a `true` element of `A`, or `0` if not found.
Find the previous linear index <= `i` of a `true` element of `A`, or `nothing` if not found.

# Examples
```jldoctest
Expand All @@ -1623,8 +1623,8 @@ julia> A = [false false; true true]
julia> findprev(A,2)
2

julia> findprev(A,1)
0
julia> findprev(A,1) == nothing
true
```
"""
function findprev(A, start::Integer)
Expand All @@ -1639,14 +1639,14 @@ function findprev(A, start::Integer)
a != 0 && return i
i = prevind(A, i)
end
return 0
return nothing
end

"""
findlast(A)

Return the linear index of the last `true` value in `A`.
Return `0` if there is no `true` value in `A`.
Return `nothing` if there is no `true` value in `A`.

# Examples
```jldoctest
Expand All @@ -1660,8 +1660,8 @@ julia> findlast(A)

julia> A = falses(2,2);

julia> findlast(A)
0
julia> findlast(A) == nothing
true
```
"""
findlast(A) = findprev(A, endof(A))
Expand All @@ -1670,7 +1670,7 @@ findlast(A) = findprev(A, endof(A))
findprev(predicate::Function, A, i::Integer)

Find the previous linear index <= `i` of an element of `A` for which `predicate` returns `true`, or
`0` if not found.
`nothing` if not found.

# Examples
```jldoctest
Expand All @@ -1679,8 +1679,8 @@ julia> A = [4 6; 1 2]
4 6
1 2

julia> findprev(isodd, A, 1)
0
julia> findprev(isodd, A, 1) == nothing
true

julia> findprev(isodd, A, 3)
2
Expand All @@ -1692,14 +1692,14 @@ function findprev(testf::Function, A, start::Integer)
testf(A[i]) && return i
i = prevind(A, i)
end
return 0
return nothing
end

"""
findlast(predicate::Function, A)

Return the linear index of the last element of `A` for which `predicate` returns `true`.
Return `0` if there is no such element.
Return `nothing` if there is no such element.

# Examples
```jldoctest
Expand All @@ -1711,8 +1711,8 @@ julia> A = [1 2; 3 4]
julia> findlast(isodd, A)
2

julia> findlast(x -> x > 5, A)
0
julia> findlast(x -> x > 5, A) == nothing
true
```
"""
findlast(testf::Function, A) = findprev(testf, A, endof(A))
Expand Down
40 changes: 21 additions & 19 deletions base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1459,13 +1459,13 @@ function unsafe_bitfindnext(Bc::Vector{UInt64}, start::Integer)
end
end
end
return 0
return nothing
end

# returns the index of the next non-zero element, or 0 if all zeros
# returns the index of the next true element, or nothing if all false
function findnext(B::BitArray, start::Integer)
start > 0 || throw(BoundsError(B, start))
start > length(B) && return 0
start > length(B) && return nothing
unsafe_bitfindnext(B.chunks, start)
end

Expand All @@ -1474,11 +1474,11 @@ end
# aux function: same as findnext(~B, start), but performed without temporaries
function findnextnot(B::BitArray, start::Integer)
start > 0 || throw(BoundsError(B, start))
start > length(B) && return 0
start > length(B) && return nothing

Bc = B.chunks
l = length(Bc)
l == 0 && return 0
l == 0 && return nothing

chunk_start = _div64(start-1)+1
within_chunk_start = _mod64(start-1)
Expand All @@ -1499,15 +1499,16 @@ function findnextnot(B::BitArray, start::Integer)
elseif Bc[l] | mask != _msk_end(B)
return (l-1) << 6 + trailing_ones(Bc[l] | mask) + 1
end
return 0
return nothing
end
findfirstnot(B::BitArray) = findnextnot(B,1)

# returns the index of the first matching element
function findnext(B::BitArray, v, start::Integer)
function findnext(pred::EqualTo, B::BitArray, start::Integer)
v = pred.x
v == false && return findnextnot(B, start)
v == true && return findnext(B, start)
return 0
return nothing
end
#findfirst(B::BitArray, v) = findnext(B, 1, v) ## defined in array.jl

Expand All @@ -1519,9 +1520,9 @@ function findnext(testf::Function, B::BitArray, start::Integer)
f0 && !f1 && return findnextnot(B, start)

start > 0 || throw(BoundsError(B, start))
start > length(B) && return 0
start > length(B) && return nothing
f0 && f1 && return Int(start)
return 0 # last case: !f0 && !f1
return nothing # last case: !f0 && !f1
end
#findfirst(testf::Function, B::BitArray) = findnext(testf, B, 1) ## defined in array.jl

Expand All @@ -1540,18 +1541,18 @@ function unsafe_bitfindprev(Bc::Vector{UInt64}, start::Integer)
end
end
end
return 0
return nothing
end

# returns the index of the previous non-zero element, or 0 if all zeros
# returns the index of the previous true element, or nothing if all false
function findprev(B::BitArray, start::Integer)
start > 0 || return 0
start > 0 || return nothing
start > length(B) && throw(BoundsError(B, start))
unsafe_bitfindprev(B.chunks, start)
end

function findprevnot(B::BitArray, start::Integer)
start > 0 || return 0
start > 0 || return nothing
start > length(B) && throw(BoundsError(B, start))

Bc = B.chunks
Expand All @@ -1570,15 +1571,16 @@ function findprevnot(B::BitArray, start::Integer)
end
end
end
return 0
return nothing
end
findlastnot(B::BitArray) = findprevnot(B, length(B))

# returns the index of the previous matching element
function findprev(B::BitArray, v, start::Integer)
function findprev(pred::EqualTo, B::BitArray, start::Integer)
v = pred.x
v == false && return findprevnot(B, start)
v == true && return findprev(B, start)
return 0
return nothing
end
#findlast(B::BitArray, v) = findprev(B, 1, v) ## defined in array.jl

Expand All @@ -1589,10 +1591,10 @@ function findprev(testf::Function, B::BitArray, start::Integer)
!f0 && f1 && return findprev(B, start)
f0 && !f1 && return findprevnot(B, start)

start > 0 || return 0
start > 0 || return nothing
start > length(B) && throw(BoundsError(B, start))
f0 && f1 && return Int(start)
return 0 # last case: !f0 && !f1
return nothing # last case: !f0 && !f1
end
#findlast(testf::Function, B::BitArray) = findprev(testf, B, 1) ## defined in array.jl

Expand Down
6 changes: 4 additions & 2 deletions base/bitset.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,16 @@ function _bits_findnext(b::Bits, start::Int)
# start is 0-based
# @assert start >= 0
_div64(start) + 1 > length(b) && return -1
unsafe_bitfindnext(b, start+1) - 1
ind = unsafe_bitfindnext(b, start+1)
ind === nothing ? -1 : ind - 1
end

function _bits_findprev(b::Bits, start::Int)
# start is 0-based
# @assert start <= 64 * length(b) - 1
start >= 0 || return -1
unsafe_bitfindprev(b, start+1) - 1
ind = unsafe_bitfindprev(b, start+1)
ind === nothing ? -1 : ind - 1
end

# An internal function for setting the inclusion bit for a given integer
Expand Down
2 changes: 1 addition & 1 deletion base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ function display_error(io::IO, er, bt)
print_with_color(Base.error_color(), io, "ERROR: "; bold = true)
# remove REPL-related frames from interactive printing
eval_ind = findlast(addr->Base.REPL.ip_matches_func(addr, :eval), bt)
if eval_ind != 0
if eval_ind !== nothing
bt = bt[1:eval_ind-1]
end
showerror(IOContext(io, :limit => true), er, bt)
Expand Down
4 changes: 2 additions & 2 deletions base/combinatorics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function permute!!(a, p::AbstractVector{<:Integer})
count = 0
start = 0
while count < length(a)
ptr = start = findnext(!iszero, p, start+1)
ptr = start = findnext(!iszero, p, start+1)::Int
temp = a[start]
next = p[start]
count += 1
Expand Down Expand Up @@ -125,7 +125,7 @@ function invpermute!!(a, p::AbstractVector{<:Integer})
count = 0
start = 0
while count < length(a)
start = findnext(!iszero, p, start+1)
start = findnext(!iszero, p, start+1)::Int
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we actually sure all AbstractArray implementations will return an Int? You could also try using notnothing(...), which throws when nothing is passed to it, which should allow the compiler to assert the type (need to check that).

BTW, how did you find the places where this assertion can be added?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyplace where the code didn't seem to check for a 0 return but then indexed it, I assumed it was guaranteed to succeed.

temp = a[start]
next = p[start]
count += 1
Expand Down
2 changes: 1 addition & 1 deletion base/event.jl
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ function ensure_rescheduled(othertask::Task)
# also need to return it to the runnable state
# before throwing an error
i = findfirst(t->t===ct, Workqueue)
i == 0 || deleteat!(Workqueue, i)
i === nothing || deleteat!(Workqueue, i)
ct.state = :runnable
end
nothing
Expand Down
2 changes: 1 addition & 1 deletion base/file.jl
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ function tempname(temppath::AbstractString,uunique::UInt32)
tempp = cwstring(temppath)
tname = Vector{UInt16}(uninitialized, 32767)
uunique = ccall(:GetTempFileNameW,stdcall,UInt32,(Ptr{UInt16},Ptr{UInt16},UInt32,Ptr{UInt16}), tempp,temp_prefix,uunique,tname)
lentname = findfirst(iszero,tname)-1
lentname = coalesce(findfirst(iszero,tname), 0)-1
if uunique == 0 || lentname <= 0
error("GetTempFileName failed: $(Libc.FormatMessage())")
end
Expand Down
1 change: 1 addition & 0 deletions base/filesystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import Base:
nb_available, position, read, read!, readavailable, seek, seekend, show,
skip, stat, unsafe_read, unsafe_write, transcode, uv_error, uvhandle,
uvtype, write
using Base: coalesce

if Sys.iswindows()
import Base: cwstring
Expand Down
4 changes: 2 additions & 2 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1822,7 +1822,7 @@ function builtin_tfunction(@nospecialize(f), argtypes::Array{Any,1},
tf = t_ifunc[iidx]
else
fidx = findfirst(x->x===f, t_ffunc_key)
if fidx == 0
if fidx === nothing
# unknown/unhandled builtin function
return Any
end
Expand Down Expand Up @@ -5147,7 +5147,7 @@ function statement_cost(ex::Expr, line::Int, src::CodeInfo, mod::Module, params:
return plus_saturate(argcost, isknowntype(ex.typ) ? 4 : params.inline_nonleaf_penalty)
end
fidx = findfirst(x->x===f, t_ffunc_key)
if fidx == 0
if fidx === nothing
# unknown/unhandled builtin or anonymous function
# Use the generic cost of a direct function call
return plus_saturate(argcost, 20)
Expand Down
Loading