I’m concerned about the loss of type-stability in the find* etc. functions, changing everything to return nothing
for the not found case.
While that is important for abstract arrays and associative structures, for strings, where there is a contract that AbstractStrings
are always 1-based indexed, returning nothing
instead of 0
just makes the code more difficult.
In my quick testing with some short strings and findfirst
, the version using nothing is 3.3x slower.
Instead, why not add a function that returns the sentinel value needed for that particular type?
notfound(::Type{<:Any}) = nothing
notfound(::Type{<:AbstractString}) = 0
notfound(val::T) where {T} = notfound(T)
For arrays also, those could still define a sentinel value of zero, if they are not OffsetArrays, to get back the performance lost by the find* changes. Also, even for OffsetArrays, if typemin(Int)
is not allowed as the first index, then that could be used as the sentinel, keeping the return values type-stable.
CC: @jeff.bezanson, @nalimilan
Note: I also think that seeing in code:
ret = findfirst(a, b)
ret == notfound(b) && ...
would be more readable than either the old way with 0
, or the new way with nothing