-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
find(next|prev|last|first) for failed matches #36768
Comments
This should absolutely be consistent—indicating no match two different ways is definitely a bug. It may, however, be a bug that people depend on, so while this should certainly be fixed, it should only be changed in a minor release. |
The behavior has changed on current master. However, it’s still not consistent: julia> findnext("", "abc", 5)
ERROR: BoundsError: attempt to access 3-element Vector{UInt8} at index [5]
[...]
julia> findprev("", "abc", -100)
-100:-101
julia> findprev("", "abc", 100)
0:-1 I think the In addition, I think the behavior of |
EDIT: I misunderstood the behavior of Here is a suggestion of reference implementation (of course, suboptimal in terms of performance): function findnext(a, b, i)
i = max(i, firstindex(b))
j = i + ncodeunits(a) - 1
while checkbounds(Bool, b, i:j)
a == b[i:j] && return i:j
i += 1; j += 1
end
return nothing
end
function findprev(a, b, j)
j = min(j, lastindex(b))
i = j - ncodeunits(a) + 1
while checkbounds(Bool, b, i:j)
a == b[i:j] && return i:j
i -= 1; j -= 1
end
return nothing
end
findfirst(a, b) = findnext(a, b, firstindex(b))
findlast(a, b) = findprev(a, b, lastindex(b)) I think throwing an exception is never useful when searching a string pattern, and the minimal, self-evident behavior that can be explained with a simple reference implementation as above is most consistent and thus least confusing. |
Can you explain why you think that throwing an exception is not useful? |
Because I cannot think of a situation where throwing an exception is useful? |
I think some formal description of the behavior is needed in order to find a consistent solution. Let Here are more formal definitions:
There is no need to throw an exception of This is okay. But we need to consider corner cases where So, with this constraint, we can modify the previous definitions as follows:
And the following is a reference implementation of the modified versions: function findnext(a, b, i)
if i > lastindex(b) + 1
return nothing
elseif i < firstindex(b)
i = firstindex(b)
elseif i ≠ thisind(b, i)
i = nextind(b, i)
end
while true
startswith(b[i:end], a) && return i:i+lastindex(a)-1
i > lastindex(b) && return nothing
i = nextind(b, i)
end
end
function findprev(a, b, i)
if i < firstindex(b) - 1
return nothing
elseif i > lastindex(b)
i = lastindex(b)
elseif i ≠ thisind(b, i)
i = thisind(b, i)
end
while true
endswith(b[begin:i], a) && return i-lastindex(a)+1:i
i < firstindex(b) && return nothing
i = prevind(b, i)
end
end
findfirst(a, b) = findnext(a, b, firstindex(b))
findlast(a, b) = findprev(a, b, lastindex(b)) |
Another strange behavior:
|
Related issue #29565 |
Sometimes
find
is returningnothing
when the match fails, sometimes it returns0:-1
—this is a bit confusing. There seems to be some uses of thesomething
function in base/strings/search.jl, where there probably shouldn't be any uses. Discovered while trying to test dcd4f3e.The text was updated successfully, but these errors were encountered: