Skip to content

Commit

Permalink
Add unexported find* functions returning nothing
Browse files Browse the repository at this point in the history
Change methods added to Base functions to return 0 on 0.6, which
matches what already happens without the optimized methods.
  • Loading branch information
nalimilan committed Feb 3, 2018
1 parent 3058197 commit b562683
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 40 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,9 @@ Currently, the `@compat` macro supports the following syntaxes:
* `search` is now `findfirst`/`findnext` and `rsearch` is now `findlast`/`findprev`,
sometimes combined with `equalto` or `occursin` ([#24673]).

* `Compat.findfirst`, `Compat.findnext`, `Compat.findlast` and `Compat.findprev`,
return `nothing` when no match is found (rather than `0`) as on Julia 0.7 ([#24673]).

* `findin(a, b)` is now `findall(occursin(b), a)` ([#24673]).

* `indmin` and `indmax` are now `argmin` and `argmax`, respectively ([#25654]).
Expand Down
77 changes: 43 additions & 34 deletions src/Compat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1510,9 +1510,12 @@ end
export lastindex
end

@static if VERSION < v"0.7.0-DEV.3272"
import Base: in, findfirst, findnext, findlast, findprev

@static if VERSION >= v"0.7.0-DEV.3272"
findnext(xs...) = Base.findnext(xs...)
findfirst(xs...) = Base.findfirst(xs...)
findprev(xs...) = Base.findprev(xs...)
findlast(xs...) = Base.findlast(xs...)
else
struct OccursIn{T} <: Function
x::T

Expand All @@ -1522,41 +1525,47 @@ end
const occursin = OccursIn
export occursin

zero2nothing(x) = x == 0 ? nothing : x
zero2nothing(x::Integer) = x == 0 ? nothing : x
zero2nothing(x) = x

findnext(xs...) = zero2nothing(Base.findnext(xs...))
findfirst(xs...) = zero2nothing(Base.findfirst(xs...))
findprev(xs...) = zero2nothing(Base.findprev(xs...))
findlast(xs...) = zero2nothing(Base.findlast(xs...))

findnext(r::Regex, s::AbstractString, idx::Integer) = search(s, r, idx)
findfirst(r::Regex, s::AbstractString) = search(s, r)
findnext(c::EqualTo{Char}, s::AbstractString, i::Integer) = zero2nothing(search(s, c.x, i))
findfirst(c::EqualTo{Char}, s::AbstractString) = zero2nothing(search(s, c.x))
findnext(b::EqualTo{<:Union{Int8,UInt8}}, a::Vector{<:Union{Int8,UInt8}}, i::Integer) =
zero2nothing(search(a, b.x, i))
findfirst(b::EqualTo{<:Union{Int8,UInt8}}, a::Vector{<:Union{Int8,UInt8}}) =
zero2nothing(search(a, b.x))
Base.findnext(r::Regex, s::AbstractString, idx::Integer) = search(s, r, idx)
Base.findfirst(r::Regex, s::AbstractString) = search(s, r)
Base.findnext(c::EqualTo{Char}, s::AbstractString, i::Integer) = search(s, c.x, i)
Base.findfirst(c::EqualTo{Char}, s::AbstractString) = search(s, c.x)
Base.findnext(b::EqualTo{<:Union{Int8,UInt8}}, a::Vector{<:Union{Int8,UInt8}}, i::Integer) =
search(a, b.x, i)
Base.findfirst(b::EqualTo{<:Union{Int8,UInt8}}, a::Vector{<:Union{Int8,UInt8}}) =
search(a, b.x)

findnext(c::OccursIn{<:Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}},
Base.findnext(c::OccursIn{<:Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}},
s::AbstractString, i::Integer) =
zero2nothing(search(s, c.x, i))
findfirst(c::OccursIn{<:Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}},
search(s, c.x, i)
Base.findfirst(c::OccursIn{<:Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}},
s::AbstractString) =
zero2nothing(search(s, c.x))
findnext(t::AbstractString, s::AbstractString, i::Integer) = search(s, t, i)
findfirst(t::AbstractString, s::AbstractString) = search(s, t)

findfirst(delim::EqualTo{UInt8}, buf::IOBuffer) = zero2nothing(search(buf, delim.x))

findprev(c::EqualTo{Char}, s::AbstractString, i::Integer) = zero2nothing(rsearch(s, c.x, i))
findlast(c::EqualTo{Char}, s::AbstractString) = zero2nothing(rsearch(s, c.x))
findprev(b::EqualTo{<:Union{Int8,UInt8}}, a::Vector{<:Union{Int8,UInt8}}, i::Integer) =
zero2nothing(rsearch(a, b.x, i))
findlast(b::EqualTo{<:Union{Int8,UInt8}}, a::Vector{<:Union{Int8,UInt8}}) =
zero2nothing(rsearch(a, b.x))

findprev(c::OccursIn{<:Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}},
s::AbstractString, i::Integer) = zero2nothing(rsearch(s, c.x, i))
findlast(c::OccursIn{<:Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}},
s::AbstractString) = zero2nothing(rsearch(s, c.x))
findprev(t::AbstractString, s::AbstractString, i::Integer) = rsearch(s, t, i)
findlast(t::AbstractString, s::AbstractString) = rsearch(s, t)
search(s, c.x)
Base.findnext(t::AbstractString, s::AbstractString, i::Integer) = search(s, t, i)
Base.findfirst(t::AbstractString, s::AbstractString) = search(s, t)

Base.findfirst(delim::EqualTo{UInt8}, buf::IOBuffer) = search(buf, delim.x)

Base.findprev(c::EqualTo{Char}, s::AbstractString, i::Integer) = rsearch(s, c.x, i)
Base.findlast(c::EqualTo{Char}, s::AbstractString) = rsearch(s, c.x)
Base.findprev(b::EqualTo{<:Union{Int8,UInt8}}, a::Vector{<:Union{Int8,UInt8}}, i::Integer) =
rsearch(a, b.x, i)
Base.findlast(b::EqualTo{<:Union{Int8,UInt8}}, a::Vector{<:Union{Int8,UInt8}}) =
rsearch(a, b.x)

Base.findprev(c::OccursIn{<:Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}},
s::AbstractString, i::Integer) = rsearch(s, c.x, i)
Base.findlast(c::OccursIn{<:Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}},
s::AbstractString) = rsearch(s, c.x)
Base.findprev(t::AbstractString, s::AbstractString, i::Integer) = rsearch(s, t, i)
Base.findlast(t::AbstractString, s::AbstractString) = rsearch(s, t)

findall(b::OccursIn, a) = findin(a, b.x)
# To fix ambiguity
Expand Down
27 changes: 21 additions & 6 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1307,30 +1307,45 @@ end
@test lastindex(zeros(4,4)) == 16

# 0.7.0-DEV.3415
for (f1, f2, i) in ((findfirst, findnext, 1), (findlast, findprev, 2))
for (f1, f2, i) in ((Compat.findfirst, Compat.findnext, 1),
(Compat.findlast, Compat.findprev, 2))
# Generic methods
@test f1(equalto(0), [1, 0]) == f2(equalto(0), [1, 0], i) == 2
@test f1(equalto(9), [1, 0]) == f2(equalto(9), [1, 0], i) == nothing
@test f1(occursin([0, 2]), [1, 0]) == f2(occursin([0, 2]), [1, 0], i) == 2
@test f1(occursin([0, 2]), [1, 9]) == f2(occursin([0, 2]), [1, 9], i) == nothing
@test f1([true, false]) == f2([true, false], i) == 1
@test f1([false, false]) == f2([false, false], i) == nothing

# Specific methods
@test f2(equalto('a'), "ba", i) == f1(equalto('a'), "ba") == 2
for S in (Int8, UInt8), T in (Int8, UInt8)
# Bug in Julia 0.6
f1 === findlast && VERSION < v"0.7.0-DEV.3272" && continue
f1 === Compat.findlast && VERSION < v"0.7.0-DEV.3272" && continue
@test f2(equalto(S(1)), T[0, 1], i) == f1(equalto(S(1)), T[0, 1]) == 2
@test f2(equalto(S(9)), T[0, 1], i) == f1(equalto(S(9)), T[0, 1]) == nothing
end
for chars in (['a', 'z'], Set(['a', 'z']), ('a', 'z'))
@test f2(occursin(chars), "ba", i) == f1(occursin(chars), "ba") == 2
@test f2(occursin(chars), "bx", i) == f1(occursin(chars), "bx") == nothing
end
end
for (f1, f2, i) in ((findfirst, findnext, 1),
(findlast, findprev, 2),
(Compat.findfirst, Compat.findnext, 1),
(Compat.findlast, Compat.findprev, 2))
@test f2("a", "ba", i) == f1("a", "ba") == 2:2
@test f2("z", "ba", i) == f1("z", "ba") == 0:-1
end
@test findnext(r"a", "ba", 1) == findfirst(r"a", "ba") == 2:2
@test findnext(r"z", "ba", 1) == findfirst(r"z", "ba") == 0:-1
@test findfirst(equalto(UInt8(0)), IOBuffer(UInt8[1, 0])) == 2
@test findfirst(equalto(UInt8(9)), IOBuffer(UInt8[1, 0])) == nothing
for (f1, f2, i) in ((findfirst, findnext, 1),
(Compat.findfirst, Compat.findnext, 1))
@test f2(r"a", "ba", 1) == f1(r"a", "ba") == 2:2
@test f2(r"z", "ba", 1) == f1(r"z", "ba") == 0:-1
end

@test Compat.findfirst(equalto(UInt8(0)), IOBuffer(UInt8[1, 0])) == 2
@test Compat.findfirst(equalto(UInt8(9)), IOBuffer(UInt8[1, 0])) == nothing

@test findall([true, false, true]) == [1, 3]
@test findall(occursin([1, 2]), [1]) == [1]

Expand Down

0 comments on commit b562683

Please sign in to comment.