# Strange comparison in Base's split method

**URL:** <https://discourse.julialang.org/t/strange-comparison-in-bases-split-method/38321>\
**Category:** Internals & Design\
**Created:** [April 26, 2020, 1:55pm UTC](https://discourse.julialang.org/t/strange-comparison-in-bases-split-method/38321 "2020-04-26T13:55:47Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [April 26, 2020, 1:55pm UTC](https://discourse.julialang.org/t/strange-comparison-in-bases-split-method/38321/1 "2020-04-26T13:55:47Z")

</div>

> _Moderator’s note: this was split from [Non-friendly documentation - #49 by rjmoses](https://discourse.julialang.org/t/non-friendly-documentation/38109/49), but the initial post is mirrored here as an edited-in quote:_

> [@Non-friendly documentation](https://discourse.julialang.org/t/non-friendly-documentation/38109/49):
>
> Specifically, I tripped across a statement in the split function that read “if r != 0:-1 …”. I have spent about 3 hours trying to find a reference that explains the “0:-1”. I have tried testing it in REPL, but it always seems to come back true.
> 
> Looking in the Punctuation section, it defines “a:b” as a binary infix operator to construct a range of a to b which make sense to me.
> 
> But where I get tripped up is the 0:-1! What does this mean?
> 
> If it means a range of 0 to -1, how does -1 play into to this? Otherwise what does it mean?

It seems to be a weird way of checking that `r` is not an empty array:

```julia
julia> typeof(0:-1)
UnitRange{Int64}

julia> collect(0:-1)
0-element Array{Int64,1}

julia> a = rand(3)
3-element Array{Float64,1}:
 0.7815764925085253
 0.8167278058427023
 0.6665929228579621

julia> a == 0:-1
false

julia> b = Array{Float64,1}()
0-element Array{Float64,1}

julia> b == 0:-1
true

```

---

<div class="post-metadata">

**Author:** ![rjmoses](https://avatars.discourse-cdn.com/v4/letter/r/90db22/32.png) [@rjmoses](https://discourse.julialang.org/u/rjmoses)\
**Post date:** [April 26, 2020, 4:01pm UTC](https://discourse.julialang.org/t/strange-comparison-in-bases-split-method/38321/2 "2020-04-26T16:01:47Z")

</div>

It seems that way to me as well, but it is straight from the Base:split() function:

…  
r = something(findfirst(splitter,str), 0)  
if r != 0:-1  
j, k = first(r), nextind(str,last(r))  
while 0 \< j \<= n && length(strs) != limit-1  
…

As near as I can guess, findfirst() returns nothing or the index of the character and then something() returns either the index or 0 if nothing.

Then, the if tests the return against the range of 0 or not 0.

I wonder why the author used the range instead of just saying “if r != 0…”.

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [April 26, 2020, 11:34pm UTC](https://discourse.julialang.org/t/strange-comparison-in-bases-split-method/38321/3 "2020-04-26T23:34:29Z")

</div>

I wonder how this bit of obfuscation got in?

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [April 27, 2020, 4:32pm UTC](https://discourse.julialang.org/t/strange-comparison-in-bases-split-method/38321/4 "2020-04-27T16:32:20Z")

</div>

> [@rjmoses](#):
>
> I wonder why the author used the range instead of just saying “if r != 0…”.

Really nice catch. And this points to a big thing I see in many beginners (albeit in reverse). Error attribution is _hard_ when you’re learning a new language. In this case, the error is in Julia source, but you’re thinking your mental model is wrong. More frequently I see the reverse.

On this bug: I don’t believe it affects behavior, but it is now a missing optimization I think. It’d be awesome if you’d want to correct it! I _think_ it should be written:

```julia
r =findfirst(splitter,str)
if r !== nothing

```

This mistake has been here for two years and has survived multiple touches from core devs. 🙂 It probably wasn’t caught because it’s not going to trip any unit tests, and will only really show up as a performance issue if you have a _really_ long string you’re splitting and the splitter isn’t found.

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [April 27, 2020, 5:46pm UTC](https://discourse.julialang.org/t/strange-comparison-in-bases-split-method/38321/5 "2020-04-27T17:46:30Z")

</div>

We are not looking at the same code, are we? I see this at [https://github.com/JuliaLang/julia/blob/9b7ea2f0b3bf4f1062eb2cee86f3cfcb197e54eb/base/strings/util.jl#L328](https://github.com/JuliaLang/julia/blob/9b7ea2f0b3bf4f1062eb2cee86f3cfcb197e54eb/base/strings/util.jl#L328)

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [April 27, 2020, 5:55pm UTC](https://discourse.julialang.org/t/strange-comparison-in-bases-split-method/38321/6 "2020-04-27T17:55:29Z")

</div>

No, that’s exactly where I’m looking! Here’s the archaeology: It had been like this:

[https://github.com/JuliaLang/julia/blob/69f9c2ea4738ef24c17fd10151f11bf3ea12f43a/base/strings/util.jl#L293-L294](https://github.com/JuliaLang/julia/blob/69f9c2ea4738ef24c17fd10151f11bf3ea12f43a/base/strings/util.jl#L293-L294)

The sentinel value for `search`’s not found used to be `0:-1`. Two separate API changes moved this to `findfirst` with a sentinel value of `nothing`, but those were both huge changes that touches many lines of code and required lots of menial fixes… so this one got missed.

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [April 27, 2020, 6:01pm UTC](https://discourse.julialang.org/t/strange-comparison-in-bases-split-method/38321/7 "2020-04-27T18:01:24Z")

</div>

Oh, I am looking at Julia latest. The line there reads `r = something(findfirst(splitter,str), 0)`.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [April 27, 2020, 6:04pm UTC](https://discourse.julialang.org/t/strange-comparison-in-bases-split-method/38321/8 "2020-04-27T18:04:49Z")

</div>

Right, the `something` is part of the bug. What I wrote is how I think it should be written.

---

<div class="post-metadata">

**Author:** ![rjmoses](https://avatars.discourse-cdn.com/v4/letter/r/90db22/32.png) [@rjmoses](https://discourse.julialang.org/u/rjmoses)\
**Post date:** [April 28, 2020, 12:39am UTC](https://discourse.julialang.org/t/strange-comparison-in-bases-split-method/38321/9 "2020-04-28T00:39:21Z")

</div>

The “if r !== nothing…” makes it even clearer

I will change my local source and check it out.

Thanks

---

<div class="post-metadata">

**Author:** ![Ralph\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ralph_smith/32/10344_2.png) [@Ralph\_Smith](https://discourse.julialang.org/u/Ralph_Smith)\
**Post date:** [April 28, 2020, 2:01am UTC](https://discourse.julialang.org/t/strange-comparison-in-bases-split-method/38321/10 "2020-04-28T02:01:48Z")

</div>

> [@mbauman](#):
>
> This mistake has been here for two years and has survived multiple touches from core devs. 🙂 It probably wasn’t caught because it’s not going to trip any unit tests

And it passed in the first place because `==` falls back to `===` for disparate types, which seems like a bug-breeder. Is there a document providing the rationale for this fallback?

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [April 28, 2020, 1:33pm UTC](https://discourse.julialang.org/t/strange-comparison-in-bases-split-method/38321/11 "2020-04-28T13:33:06Z")

</div>

Amusingly enough, I stumbled across a comment (by myself) about this from last year while reviewing a separate PR. My initial assessment in this thread isn’t the whole story because `findfirst("asdf", "")` returns `1:0`, so that branch _actually is doing something in real code!_

[https://github.com/JuliaLang/julia/pull/32348/files#r294443966](https://github.com/JuliaLang/julia/pull/32348/files#r294443966)
