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

make coalesce handle only missing; add something #27258

Merged
merged 2 commits into from
May 30, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
make coalesce handle only missing; add something to handle `not…
…hing`/`Some`

fixes #26927
  • Loading branch information
JeffBezanson authored and Viral B. Shah committed May 28, 2018
commit 13330484f2d4b2be4a8caaa9220e23b0ea106821
2 changes: 1 addition & 1 deletion base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ color_normal = text_colors[:normal]
function repl_color(key, default)
env_str = get(ENV, key, "")
c = tryparse(Int, env_str)
c_conv = coalesce(c, Symbol(env_str))
c_conv = something(c, Symbol(env_str))
haskey(text_colors, c_conv) ? c_conv : default
end

Expand Down
2 changes: 1 addition & 1 deletion base/compiler/ssair/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ function compute_ir_line_annotations(code::IRCode)
first_mismatch = nothing
end
end
last_depth = coalesce(first_mismatch, x+1)-1
last_depth = something(first_mismatch, x+1)-1
if min(depth, last_depth) > last_printed_depth
printing_depth = min(depth, last_printed_depth + 1)
last_printed_depth = printing_depth
Expand Down
90 changes: 45 additions & 45 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -730,10 +730,10 @@ end
@deprecate charwidth textwidth

@deprecate find(x::Number) findall(!iszero, x)
@deprecate findnext(A, v, i::Integer) coalesce(findnext(isequal(v), A, i), 0)
@deprecate findfirst(A, v) coalesce(findfirst(isequal(v), A), 0)
@deprecate findprev(A, v, i::Integer) coalesce(findprev(isequal(v), A, i), 0)
@deprecate findlast(A, v) coalesce(findlast(isequal(v), A), 0)
@deprecate findnext(A, v, i::Integer) something(findnext(isequal(v), A, i), 0)
@deprecate findfirst(A, v) something(findfirst(isequal(v), A), 0)
@deprecate findprev(A, v, i::Integer) something(findprev(isequal(v), A, i), 0)
@deprecate findlast(A, v) something(findlast(isequal(v), A), 0)
# to fix ambiguities introduced by deprecations
findnext(pred::Function, A, i::Integer) = invoke(findnext, Tuple{Function, Any, Any}, pred, A, i)
findprev(pred::Function, A, i::Integer) = invoke(findprev, Tuple{Function, Any, Any}, pred, A, i)
Expand Down Expand Up @@ -1217,47 +1217,47 @@ end
@deprecate_binding HasOrder Ordered
@deprecate_binding ArithmeticOverflows ArithmeticWraps

@deprecate search(str::Union{String,SubString}, re::Regex, idx::Integer) coalesce(findnext(re, str, idx), 0:-1)
@deprecate search(s::AbstractString, r::Regex, idx::Integer) coalesce(findnext(r, s, idx), 0:-1)
@deprecate search(s::AbstractString, r::Regex) coalesce(findfirst(r, s), 0:-1)
@deprecate search(s::AbstractString, c::Char, i::Integer) coalesce(findnext(isequal(c), s, i), 0)
@deprecate search(s::AbstractString, c::Char) coalesce(findfirst(isequal(c), s), 0)
@deprecate search(a::ByteArray, b::Union{Int8,UInt8}, i::Integer) coalesce(findnext(isequal(b), a, i), 0)
@deprecate search(a::ByteArray, b::Union{Int8,UInt8}) coalesce(findfirst(isequal(b), a), 0)
@deprecate search(a::String, b::Union{Int8,UInt8}, i::Integer) coalesce(findnext(isequal(b), unsafe_wrap(Vector{UInt8}, a), i), 0)
@deprecate search(a::String, b::Union{Int8,UInt8}) coalesce(findfirst(isequal(b), unsafe_wrap(Vector{UInt8}, a)), 0)
@deprecate search(a::ByteArray, b::Char, i::Integer) coalesce(findnext(isequal(UInt8(b)), a, i), 0)
@deprecate search(a::ByteArray, b::Char) coalesce(findfirst(isequal(UInt8(b)), a), 0)

@deprecate search(s::AbstractString, c::Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}, i::Integer) coalesce(findnext(in(c), s, i), 0)
@deprecate search(s::AbstractString, c::Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}) coalesce(findfirst(in(c), s), 0)
@deprecate search(s::AbstractString, t::AbstractString, i::Integer) coalesce(findnext(t, s, i), 0:-1)
@deprecate search(s::AbstractString, t::AbstractString) coalesce(findfirst(t, s), 0:-1)

@deprecate rsearch(s::AbstractString, c::Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}, i::Integer) coalesce(findprev(in(c), s, i), 0)
@deprecate rsearch(s::AbstractString, c::Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}) coalesce(findlast(in(c), s), 0)
@deprecate rsearch(s::AbstractString, t::AbstractString, i::Integer) coalesce(findprev(t, s, i), 0:-1)
@deprecate rsearch(s::AbstractString, t::AbstractString) coalesce(findlast(t, s), 0:-1)

@deprecate rsearch(str::Union{String,SubString}, re::Regex, idx::Integer) coalesce(findprev(re, str, idx), 0:-1)
@deprecate rsearch(str::Union{String,SubString}, re::Regex) coalesce(findlast(re, str), 0:-1)
@deprecate rsearch(s::AbstractString, r::Regex, idx::Integer) coalesce(findprev(r, s, idx), 0:-1)
@deprecate rsearch(s::AbstractString, r::Regex) coalesce(findlast(r, s), 0:-1)
@deprecate rsearch(s::AbstractString, c::Char, i::Integer) coalesce(findprev(isequal(c), s, i), 0)
@deprecate rsearch(s::AbstractString, c::Char) coalesce(findlast(isequal(c), s), 0)
@deprecate rsearch(a::Union{String,ByteArray}, b::Union{Int8,UInt8}, i::Integer = lastindex(a)) coalesce(findprev(isequal(b), a, i), 0)
@deprecate rsearch(a::String, b::Union{Int8,UInt8}, i::Integer = lastindex(a)) coalesce(findprev(isequal(Char(b)), a, i), 0)
@deprecate rsearch(a::ByteArray, b::Char, i::Integer = lastindex(a)) coalesce(findprev(isequal(UInt8(b)), a, i), 0)

@deprecate searchindex(s::AbstractString, t::AbstractString) first(coalesce(findfirst(t, s), 0:-1))
@deprecate searchindex(s::AbstractString, t::AbstractString, i::Integer) first(coalesce(findnext(t, s, i), 0:-1))
@deprecate rsearchindex(s::AbstractString, t::AbstractString) first(coalesce(findlast(t, s), 0:-1))
@deprecate rsearchindex(s::AbstractString, t::AbstractString, i::Integer) first(coalesce(findprev(t, s, i), 0:-1))

@deprecate searchindex(s::AbstractString, c::Char) coalesce(findfirst(isequal(c), s), 0)
@deprecate searchindex(s::AbstractString, c::Char, i::Integer) coalesce(findnext(isequal(c), s, i), 0)
@deprecate rsearchindex(s::AbstractString, c::Char) coalesce(findlast(isequal(c), s), 0)
@deprecate rsearchindex(s::AbstractString, c::Char, i::Integer) coalesce(findprev(isequal(c), s, i), 0)
@deprecate search(str::Union{String,SubString}, re::Regex, idx::Integer) something(findnext(re, str, idx), 0:-1)
@deprecate search(s::AbstractString, r::Regex, idx::Integer) something(findnext(r, s, idx), 0:-1)
@deprecate search(s::AbstractString, r::Regex) something(findfirst(r, s), 0:-1)
@deprecate search(s::AbstractString, c::Char, i::Integer) something(findnext(isequal(c), s, i), 0)
@deprecate search(s::AbstractString, c::Char) something(findfirst(isequal(c), s), 0)
@deprecate search(a::ByteArray, b::Union{Int8,UInt8}, i::Integer) something(findnext(isequal(b), a, i), 0)
@deprecate search(a::ByteArray, b::Union{Int8,UInt8}) something(findfirst(isequal(b), a), 0)
@deprecate search(a::String, b::Union{Int8,UInt8}, i::Integer) something(findnext(isequal(b), unsafe_wrap(Vector{UInt8}, a), i), 0)
@deprecate search(a::String, b::Union{Int8,UInt8}) something(findfirst(isequal(b), unsafe_wrap(Vector{UInt8}, a)), 0)
@deprecate search(a::ByteArray, b::Char, i::Integer) something(findnext(isequal(UInt8(b)), a, i), 0)
@deprecate search(a::ByteArray, b::Char) something(findfirst(isequal(UInt8(b)), a), 0)

@deprecate search(s::AbstractString, c::Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}, i::Integer) something(findnext(in(c), s, i), 0)
@deprecate search(s::AbstractString, c::Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}) something(findfirst(in(c), s), 0)
@deprecate search(s::AbstractString, t::AbstractString, i::Integer) something(findnext(t, s, i), 0:-1)
@deprecate search(s::AbstractString, t::AbstractString) something(findfirst(t, s), 0:-1)

@deprecate rsearch(s::AbstractString, c::Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}, i::Integer) something(findprev(in(c), s, i), 0)
@deprecate rsearch(s::AbstractString, c::Union{Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}}) something(findlast(in(c), s), 0)
@deprecate rsearch(s::AbstractString, t::AbstractString, i::Integer) something(findprev(t, s, i), 0:-1)
@deprecate rsearch(s::AbstractString, t::AbstractString) something(findlast(t, s), 0:-1)

@deprecate rsearch(str::Union{String,SubString}, re::Regex, idx::Integer) something(findprev(re, str, idx), 0:-1)
@deprecate rsearch(str::Union{String,SubString}, re::Regex) something(findlast(re, str), 0:-1)
@deprecate rsearch(s::AbstractString, r::Regex, idx::Integer) something(findprev(r, s, idx), 0:-1)
@deprecate rsearch(s::AbstractString, r::Regex) something(findlast(r, s), 0:-1)
@deprecate rsearch(s::AbstractString, c::Char, i::Integer) something(findprev(isequal(c), s, i), 0)
@deprecate rsearch(s::AbstractString, c::Char) something(findlast(isequal(c), s), 0)
@deprecate rsearch(a::Union{String,ByteArray}, b::Union{Int8,UInt8}, i::Integer = lastindex(a)) something(findprev(isequal(b), a, i), 0)
@deprecate rsearch(a::String, b::Union{Int8,UInt8}, i::Integer = lastindex(a)) something(findprev(isequal(Char(b)), a, i), 0)
@deprecate rsearch(a::ByteArray, b::Char, i::Integer = lastindex(a)) something(findprev(isequal(UInt8(b)), a, i), 0)

@deprecate searchindex(s::AbstractString, t::AbstractString) first(something(findfirst(t, s), 0:-1))
@deprecate searchindex(s::AbstractString, t::AbstractString, i::Integer) first(something(findnext(t, s, i), 0:-1))
@deprecate rsearchindex(s::AbstractString, t::AbstractString) first(something(findlast(t, s), 0:-1))
@deprecate rsearchindex(s::AbstractString, t::AbstractString, i::Integer) first(something(findprev(t, s, i), 0:-1))

@deprecate searchindex(s::AbstractString, c::Char) something(findfirst(isequal(c), s), 0)
@deprecate searchindex(s::AbstractString, c::Char, i::Integer) something(findnext(isequal(c), s, i), 0)
@deprecate rsearchindex(s::AbstractString, c::Char) something(findlast(isequal(c), s), 0)
@deprecate rsearchindex(s::AbstractString, c::Char, i::Integer) something(findprev(isequal(c), s, i), 0)

@deprecate ismatch(r::Regex, s::AbstractString) occursin(r, s)

Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,7 @@ export
ismissing,
missing,
skipmissing,
something,

# time
sleep,
Expand Down
2 changes: 1 addition & 1 deletion base/file.jl
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ function _win_tempname(temppath::AbstractString, uunique::UInt32)
tempp = cwstring(temppath)
tname = Vector{UInt16}(undef, 32767)
uunique = ccall(:GetTempFileNameW,stdcall,UInt32,(Ptr{UInt16},Ptr{UInt16},UInt32,Ptr{UInt16}), tempp,temp_prefix,uunique,tname)
lentname = coalesce(findfirst(iszero,tname), 0)-1
lentname = something(findfirst(iszero,tname), 0)-1
if uunique == 0 || lentname <= 0
error("GetTempFileName failed: $(Libc.FormatMessage())")
end
Expand Down
28 changes: 27 additions & 1 deletion base/missing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ showerror(io::IO, ex::MissingException) =
print(io, "MissingException: ", ex.msg)



nonmissingtype(::Type{Union{T, Missing}}) where {T} = T
nonmissingtype(::Type{Missing}) = Union{}
nonmissingtype(::Type{T}) where {T} = T
Expand Down Expand Up @@ -189,3 +188,30 @@ function Base.iterate(itr::SkipMissing, state...)
end
item, state
end

"""
coalesce(x, y...)

Return the first value in the arguments which is not equal to [`missing`](@ref),
if any. Otherwise return `missing`.

# Examples

```jldoctest
julia> coalesce(missing, 1)
1

julia> coalesce(1, missing)
1

julia> coalesce(nothing, 1) # returns `nothing`
Copy link
Member

Choose a reason for hiding this comment

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

Probably better remove this example, there's no reason to think that nothing is treated differently from any other value.

Copy link
Sponsor Member

Choose a reason for hiding this comment

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

I think the point of the example is to demonstrate that.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I understand that, but my point is that nobody would have imagined coalesce would consider nothing as a missing value, except for the fact that it was the previous behavior. And since most people won't know that history...

Anyway, not a big deal.


julia> coalesce(missing, missing)
missing
```
"""
function coalesce end

coalesce() = missing
Copy link
Member

Choose a reason for hiding this comment

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

I'd find it more natural to define coalesce(x::Missing) = throw(...). There's no reason to define a function with zero arguments AFAICT. Same remark for something.

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

This isn't ancient Rome; we understand zero now 😁

Copy link
Sponsor Member

@StefanKarpinski StefanKarpinski May 26, 2018

Choose a reason for hiding this comment

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

I 100% agree with Jeff here. Zero things is missing the same way the sum of no things is zero and the product of no things is one. If we knew the type in those cases, we would absolutely define the empty sums and products to do that; in this case we do know the type and can return missing.

Copy link
Member

@nalimilan nalimilan May 26, 2018

Choose a reason for hiding this comment

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

OK, why not, though I'm not sure in what cases it could be useful. OTOH I don't think it makes sense for something (since an error is thrown), but let's discuss it in the other thread above. EDIT: Actually now I see it's somewhat similar, even though it's not that useful since an error is thrown anyway.

coalesce(x::Missing, y...) = coalesce(y...)
coalesce(x::Any, y...) = x
8 changes: 4 additions & 4 deletions base/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -278,16 +278,16 @@ function tryparse_internal(::Type{Complex{T}}, s::Union{String,SubString{String}
end

# find index of ± separating real/imaginary parts (if any)
i₊ = coalesce(findnext(in(('+','-')), s, i), 0)
i₊ = something(findnext(in(('+','-')), s, i), 0)
if i₊ == i # leading ± sign
i₊ = coalesce(findnext(in(('+','-')), s, i₊+1), 0)
i₊ = something(findnext(in(('+','-')), s, i₊+1), 0)
end
if i₊ != 0 && s[i₊-1] in ('e','E') # exponent sign
i₊ = coalesce(findnext(in(('+','-')), s, i₊+1), 0)
i₊ = something(findnext(in(('+','-')), s, i₊+1), 0)
end

# find trailing im/i/j
iᵢ = coalesce(findprev(in(('m','i','j')), s, e), 0)
iᵢ = something(findprev(in(('m','i','j')), s, e), 0)
if iᵢ > 0 && s[iᵢ] == 'm' # im
iᵢ -= 1
if s[iᵢ] != 'i'
Expand Down
4 changes: 2 additions & 2 deletions base/path.jl
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,8 @@ function relpath(path::String, startpath::String = ".")
break
end
end
pathpart = join(path_arr[i+1:coalesce(findlast(x -> !isempty(x), path_arr), 0)], path_separator)
prefix_num = coalesce(findlast(x -> !isempty(x), start_arr), 0) - i - 1
pathpart = join(path_arr[i+1:something(findlast(x -> !isempty(x), path_arr), 0)], path_separator)
prefix_num = something(findlast(x -> !isempty(x), start_arr), 0) - i - 1
if prefix_num >= 0
prefix = pardir * path_separator
relpath_ = isempty(pathpart) ?
Expand Down
2 changes: 1 addition & 1 deletion base/shell.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function shell_parse(str::AbstractString, interpolate::Bool=true;
end
function consume_upto(j)
update_arg(s[i:prevind(s, j)])
i = coalesce(peek(st), (lastindex(s)+1,'\0'))[1]
i = something(peek(st), (lastindex(s)+1,'\0'))[1]
end
function append_arg()
if isempty(arg); arg = Any["",]; end
Expand Down
56 changes: 24 additions & 32 deletions base/some.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
A wrapper type used in `Union{Some{T}, Nothing}` to distinguish between the absence
of a value ([`nothing`](@ref)) and the presence of a `nothing` value (i.e. `Some(nothing)`).

Use [`coalesce`](@ref) to access the value wrapped by a `Some` object.
Use [`something`](@ref) to access the value wrapped by a `Some` object.
"""
struct Some{T}
value::T
Expand All @@ -33,47 +33,39 @@ function show(io::IO, x::Some)
end

"""
coalesce(x, y...)
notnothing(x)
Copy link
Member

Choose a reason for hiding this comment

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

As you noted, I think we can just remove notnothing and use something instead. I don't think we use it in situations where accidentally unwrapping Some is possible. On the contrary, I only used notnothing in places where Nullable previously required explicit unwrapping, which ensured null values were caught early. Anyway it's internal.


Return the first value in the arguments which is not equal to
either [`nothing`](@ref) or [`missing`](@ref), or the last argument.
Unwrap arguments of type [`Some`](@ref).
Throw an error if `x === nothing`, and return `x` if not.
"""
notnothing(x::Any) = x
notnothing(::Nothing) = throw(ArgumentError("nothing passed to notnothing"))

"""
something(x, y...)

Return the first value in the arguments which is not equal to [`nothing`](@ref),
if any. Otherwise throw an error.
Arguments of type [`Some`](@ref) are unwrapped.

# Examples

```jldoctest
julia> coalesce(nothing, 1)
julia> something(nothing, 1)
1

julia> coalesce(missing, 1)
julia> something(Some(1), nothing)
1

julia> coalesce(1, nothing)
1
julia> something(missing, nothing)
missing

julia> coalesce(nothing, nothing) # returns nothing, but not printed in the REPL

julia> coalesce(Some(1))
1

julia> coalesce(nothing, Some(1))
1
julia> something(nothing, nothing)
ERROR: ArgumentError: No value arguments present
```
"""
function coalesce end

coalesce(x::Any) = x
coalesce(x::Some) = x.value
coalesce(x::Nothing) = nothing
coalesce(x::Missing) = missing
coalesce(x::Any, y...) = x
coalesce(x::Some, y...) = x.value
coalesce(x::Union{Nothing, Missing}, y...) = coalesce(y...)

"""
notnothing(x)
function something end

Throw an error if `x === nothing`, and return `x` if not.
"""
notnothing(x::Any) = x
notnothing(::Nothing) = throw(ArgumentError("nothing passed to notnothing"))
something() = throw(ArgumentError("No value arguments present"))
Copy link
Member

@nalimilan nalimilan May 26, 2018

Choose a reason for hiding this comment

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

Same remark as for the zero-argument coalesce below.

something(x::Nothing, y...) = something(y...)
something(x::Some, y...) = x.value
something(x::Any, y...) = x
6 changes: 3 additions & 3 deletions base/stacktraces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module StackTraces

import Base: hash, ==, show
using Base.Printf: @printf
using Base: coalesce
using Base: something

export StackTrace, StackFrame, stacktrace

Expand Down Expand Up @@ -247,12 +247,12 @@ all frames above the specified function). Primarily used to remove `StackTraces`
from the `StackTrace` prior to returning it.
"""
function remove_frames!(stack::StackTrace, name::Symbol)
splice!(stack, 1:coalesce(findlast(frame -> frame.func == name, stack), 0))
splice!(stack, 1:something(findlast(frame -> frame.func == name, stack), 0))
return stack
end

function remove_frames!(stack::StackTrace, names::Vector{Symbol})
splice!(stack, 1:coalesce(findlast(frame -> frame.func in names, stack), 0))
splice!(stack, 1:something(findlast(frame -> frame.func in names, stack), 0))
return stack
end

Expand Down
10 changes: 5 additions & 5 deletions base/strings/search.jl
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function _searchindex(s::Union{AbstractString,ByteArray},
end
end

_searchindex(s::AbstractString, t::AbstractChar, i::Integer) = coalesce(findnext(isequal(t), s, i), 0)
_searchindex(s::AbstractString, t::AbstractChar, i::Integer) = something(findnext(isequal(t), s, i), 0)

function _search_bloom_mask(c)
UInt64(1) << (c & 63)
Expand All @@ -149,7 +149,7 @@ _nthbyte(a::Union{AbstractVector{UInt8},AbstractVector{Int8}}, i) = a[i]

function _searchindex(s::String, t::String, i::Integer)
# Check for fast case of a single byte
lastindex(t) == 1 && return coalesce(findnext(isequal(t[1]), s, i), 0)
lastindex(t) == 1 && return something(findnext(isequal(t[1]), s, i), 0)
_searchindex(unsafe_wrap(Vector{UInt8},s), unsafe_wrap(Vector{UInt8},t), i)
end

Expand All @@ -162,7 +162,7 @@ function _searchindex(s::ByteArray, t::ByteArray, i::Integer)
elseif m == 0
return 0
elseif n == 1
return coalesce(findnext(isequal(_nthbyte(t,1)), s, i), 0)
return something(findnext(isequal(_nthbyte(t,1)), s, i), 0)
end

w = m - n
Expand Down Expand Up @@ -317,7 +317,7 @@ end
function _rsearchindex(s::String, t::String, i::Integer)
# Check for fast case of a single byte
if lastindex(t) == 1
return coalesce(findprev(isequal(t[1]), s, i), 0)
return something(findprev(isequal(t[1]), s, i), 0)
elseif lastindex(t) != 0
j = i ≤ ncodeunits(s) ? nextind(s, i)-1 : i
return _rsearchindex(unsafe_wrap(Vector{UInt8}, s), unsafe_wrap(Vector{UInt8}, t), j)
Expand All @@ -339,7 +339,7 @@ function _rsearchindex(s::ByteArray, t::ByteArray, k::Integer)
elseif m == 0
return 0
elseif n == 1
return coalesce(findprev(isequal(_nthbyte(t,1)), s, k), 0)
return something(findprev(isequal(_nthbyte(t,1)), s, k), 0)
end

w = m - n
Expand Down
Loading