Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add one argument ``curried'' forms of `isequal`, `==` and `in`.
Keep the following definitions to not break Compat on julia v0.6:
 - const EqualTo = Fix2{typeof(isequal)}
 - Compat.equalto(x) = isequal(x)
 - const OccursIn = Fix2{typeof(in)}
 - Compat.occursin(x) = in(x)
  • Loading branch information
fredrikekre committed Mar 16, 2018
1 parent b43c216 commit e0437f0
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 65 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ Currently, the `@compat` macro supports the following syntaxes:
`cov(::AbstractVector; corrected=)` and `cov(::AbstractVector, ::AbstractVector; corrected=)`
are only available on 0.6. ([#21709])

* `equalto` constructs an `EqualTo` object that can be used as a predicate ([#23812]).
* `isequal`, `==` and `in` have one argument "curried" forms. For example `isequal(x)`
returns a function that compares its arguments to `x` using `isequal` ([#26436]).

* `*(::Union{Char,AbstractString},::Union{Char,AbstractString})` concatenation. ([#22512])

Expand Down Expand Up @@ -350,18 +351,18 @@ Currently, the `@compat` macro supports the following syntaxes:
* `find` is now `findall` ([#25545]).

* `search` is now `findfirst`/`findnext` and `rsearch` is now `findlast`/`findprev`,
sometimes combined with `equalto` or `occursin` ([#24673]).
sometimes combined with `isequal` or `in` ([#24673], [#26436]).

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

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

* `indmin` and `indmax` are now `argmin` and `argmax`, respectively ([#25654]).

* `Compat.indexin` accepts any iterable as first argument, returns `nothing` (rather than `0`)
for entries with no match and gives the index of the first (rather than the last) match
for entries with no match and gives the index of the first (rather than the last) match
([#25662], [#25998]).

* `isabstract` and `isleaftype` are now `isabstracttype` and `isconcretetype`, respectively
Expand Down Expand Up @@ -532,7 +533,6 @@ includes this fix. Find the minimum version from there.
[#23642]: https://github.com/JuliaLang/julia/issues/23642
[#23666]: https://github.com/JuliaLang/julia/issues/23666
[#23757]: https://github.com/JuliaLang/julia/issues/23757
[#23812]: https://github.com/JuliaLang/julia/issues/23812
[#23931]: https://github.com/JuliaLang/julia/issues/23931
[#24047]: https://github.com/JuliaLang/julia/issues/24047
[#24182]: https://github.com/JuliaLang/julia/issues/24182
Expand Down Expand Up @@ -599,4 +599,5 @@ includes this fix. Find the minimum version from there.
[#26149]: https://github.com/JuliaLang/julia/issues/26149
[#26156]: https://github.com/JuliaLang/julia/issues/26156
[#26316]: https://github.com/JuliaLang/julia/issues/26316
[#26442]: https://github.com/JuliaLang/julia/issues/26442
[#26436]: https://github.com/JuliaLang/julia/issues/26436
[#26442]: https://github.com/JuliaLang/julia/issues/26442
75 changes: 35 additions & 40 deletions src/Compat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -868,28 +868,27 @@ else
import Serialization
end

# 0.7.0-DEV.1993
@static if !isdefined(Base, :EqualTo)
if VERSION >= v"0.6.0"
include_string(@__MODULE__, """
struct EqualTo{T} <: Function
x::T
EqualTo(x::T) where {T} = new{T}(x)
end
""")
else
include_string(@__MODULE__, """
immutable EqualTo{T} <: Function
x::T
end
""")
@static if VERSION < v"0.7.0-DEV.4592"
struct Fix2{F,T} <: Function
f::F
x::T
Fix2(f::F, x::T) where {F,T} = new{F,T}(f, x)
Fix2(f::Type{F}, x::T) where {F,T} = new{F,T}(f, x)
end
(f::EqualTo)(y) = isequal(f.x, y)
const equalto = EqualTo
(f::Fix2)(y) = f.f(y, f.x)

Base.isequal(x) = Fix2(isequal, x)
Base.:(==)(x) = Fix2(==, x)
Base.in(x) = Fix2(in, x)
end
# # keep these definitions to be non breaking for 0.6 usage
@static if VERSION < v"0.7.0-DEV.1993"
const EqualTo = Fix2{typeof(isequal)}
export equalto
equalto(x) = isequal(x)
end


# 0.7.0-DEV.912
if VERSION < v"0.7.0-DEV.912"
import Base.*
Expand Down Expand Up @@ -1486,14 +1485,10 @@ end
findprev(xs...) = Base.findprev(xs...)
findlast(xs...) = Base.findlast(xs...)
else
struct OccursIn{T} <: Function
x::T

OccursIn(x::T) where {T} = new{T}(x)
end
(f::OccursIn)(y) = y in f.x
const occursin = OccursIn
# keep these definitions to be non breaking for 0.6 usage
const OccursIn = Fix2{typeof(in)}
export occursin
occursin(x) = in(x)

zero2nothing(x::Integer) = x == 0 ? nothing : x
zero2nothing(x::AbstractUnitRange{<:Integer}) = x == 0:-1 ? nothing : x
Expand All @@ -1506,41 +1501,41 @@ else

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) =
Base.findnext(c::Fix2{typeof(isequal),Char}, s::AbstractString, i::Integer) = search(s, c.x, i)
Base.findfirst(c::Fix2{typeof(isequal),Char}, s::AbstractString) = search(s, c.x)
Base.findnext(b::Fix2{typeof(isequal),<: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}}) =
Base.findfirst(b::Fix2{typeof(isequal),<:Union{Int8,UInt8}}, a::Vector{<:Union{Int8,UInt8}}) =
search(a, b.x)

Base.findnext(c::OccursIn{<:Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}},
Base.findnext(c::Fix2{typeof(in),<:Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}},
s::AbstractString, i::Integer) =
search(s, c.x, i)
Base.findfirst(c::OccursIn{<:Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}},
Base.findfirst(c::Fix2{typeof(in),<:Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}},
s::AbstractString) =
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::Base.IOBuffer) = search(buf, delim.x)
Base.findfirst(delim::Fix2{typeof(isequal),UInt8}, buf::Base.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) =
Base.findprev(c::Fix2{typeof(isequal),Char}, s::AbstractString, i::Integer) = rsearch(s, c.x, i)
Base.findlast(c::Fix2{typeof(isequal),Char}, s::AbstractString) = rsearch(s, c.x)
Base.findprev(b::Fix2{typeof(isequal),<: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}}) =
Base.findlast(b::Fix2{typeof(isequal),<:Union{Int8,UInt8}}, a::Vector{<:Union{Int8,UInt8}}) =
rsearch(a, b.x)

Base.findprev(c::OccursIn{<:Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}},
Base.findprev(c::Fix2{typeof(in),<: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}}},
Base.findlast(c::Fix2{typeof(in),<: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)
findall(b::Fix2{typeof(in)}, a) = findin(a, b.x)
# To fix ambiguity
findall(b::OccursIn, a::Number) = a in b.x ? [1] : Vector{Int}()
findall(b::Fix2{typeof(in)}, a::Number) = a in b.x ? [1] : Vector{Int}()
end

@static if VERSION < v"0.7.0-DEV.4047" #26089
Expand Down
46 changes: 27 additions & 19 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -947,13 +947,21 @@ module Test24648
end

let a = [0,1,2,3,0,1,2,3]
@test findfirst(equalto(3), [1,2,4,1,2,3,4]) == 6
@test findfirst(!equalto(1), [1,2,4,1,2,3,4]) == 2
@test findnext(equalto(1), a, 4) == 6
# @test findnext(equalto(5), a, 4) == 0
@test findlast(equalto(3), [1,2,4,1,2,3,4]) == 6
@test findprev(equalto(1), a, 4) == 2
@test findprev(equalto(1), a, 8) == 6
# curried isequal
@test findfirst(isequal(3), [1,2,4,1,2,3,4]) == 6
@test findfirst(!isequal(1), [1,2,4,1,2,3,4]) == 2
@test findnext(isequal(1), a, 4) == 6
# @test findnext(isequal(5), a, 4) == 0
@test findlast(isequal(3), [1,2,4,1,2,3,4]) == 6
@test findprev(isequal(1), a, 4) == 2
@test findprev(isequal(1), a, 8) == 6
# curried ==
@test findfirst(==(3), [1,2,4,1,2,3,4]) == 6
@test findfirst(!==(1), [1,2,4,1,2,3,4]) == 2
@test findnext(==(1), a, 4) == 6
@test findlast(==(3), [1,2,4,1,2,3,4]) == 6
@test findprev(==(1), a, 4) == 2
@test findprev(==(1), a, 8) == 6
end

# 0.7
Expand Down Expand Up @@ -1358,24 +1366,24 @@ end
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(isequal(0), [1, 0]) == f2(isequal(0), [1, 0], i) == 2
@test f1(isequal(9), [1, 0]) == f2(isequal(9), [1, 0], i) == nothing
@test f1(in([0, 2]), [1, 0]) == f2(in([0, 2]), [1, 0], i) == 2
@test f1(in([0, 2]), [1, 9]) == f2(in([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
@test f2(isequal('a'), "ba", i) == f1(isequal('a'), "ba") == 2
for S in (Int8, UInt8), T in (Int8, UInt8)
# Bug in Julia 0.6
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
@test f2(isequal(S(1)), T[0, 1], i) == f1(isequal(S(1)), T[0, 1]) == 2
@test f2(isequal(S(9)), T[0, 1], i) == f1(isequal(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
@test f2(in(chars), "ba", i) == f1(in(chars), "ba") == 2
@test f2(in(chars), "bx", i) == f1(in(chars), "bx") == nothing
end
end
@test findnext("a", "ba", 1) == findfirst("a", "ba") == 2:2
Expand All @@ -1392,11 +1400,11 @@ end
@test Compat.findnext(r"a", "ba", 1) == Compat.findfirst(r"a", "ba") == 2:2
@test Compat.findnext(r"z", "ba", 1) == Compat.findfirst(r"z", "ba") == nothing

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

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

# 0.7.0-DEV.3666
module TestUUIDs
Expand Down

0 comments on commit e0437f0

Please sign in to comment.