# The new output of findfirst is dangerous

**URL:** <https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131>\
**Category:** General Usage\
**Created:** [February 17, 2018, 5:03pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131 "2018-02-17T17:03:21Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [February 17, 2018, 5:03pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/1 "2018-02-17T17:03:21Z")

</div>

Because `findfirst` can output a `boolean` a `notthing` or an iterator and in this later case, an `0:-1` when it finds nothing.  
See this example

```julia
julia> first(findfirst(fieldnames(GMT.GMTgrid), :z))
┌ Warning: `findfirst(A, v)` is deprecated, use `findfirst(equalto(v), A)` instead.
│ caller = top-level scope
└ @ Core :0
13

julia> first(findfirst(equalto(:z), fieldnames(GMT.GMTgrid)))
13

julia> first(findfirst(equalto(:u), fieldnames(GMT.GMTgrid)))
ERROR: MethodError: no method matching start(::Nothing)
Closest candidates are:
  start(::SimpleVector) at essentials.jl:550
  start(::Base.MethodList) at reflection.jl:659
  start(::ExponentialBackOff) at error.jl:171
  ...
Stacktrace:
 [1] first(::Nothing) at .\abstractarray.jl:198
 [2] top-level scope

```

---

<div class="post-metadata">

**Author:** ![yurivish](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yurivish/32/307_2.png) [@yurivish](https://discourse.julialang.org/u/yurivish)\
**Post date:** [February 17, 2018, 5:40pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/2 "2018-02-17T17:40:17Z")

</div>

I admit to being somewhat confused by this API as well. It seems to me that using `nothing` as a null value without explicit unwrapping makes it a bit too easy to write code that fails in surprising ways when the element is not found.

Explicit unwrapping with `Some(...)` would ensure that situation is always handled, and future syntax sugar could reduce the verbosity of cases where you know that the element you’re searching for is definitely there.

The impression I got when I [asked](https://github.com/JuliaLang/julia/pull/25662#issuecomment-359270838) about this on the related GitHub issue was that this was an intentional design choice, and that the alternative (requiring explicit unwrapping) was considered too verbose in the common cases.

---

<div class="post-metadata">

**Author:** ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)\
**Post date:** [February 17, 2018, 6:28pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/3 "2018-02-17T18:28:22Z")

</div>

I was used to having it returned `0` and then managing the case. A bit taken by the decision to change this in 0.7.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 17, 2018, 6:31pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/4 "2018-02-17T18:31:52Z")

</div>

Why would you ever want to call `first` on a know scalar? And no it’s not dangerous at all. You’ve demonstrated how useful it is to catch user error.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [February 17, 2018, 6:43pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/5 "2018-02-17T18:43:14Z")

</div>

> [@yuyichao](#):
>
> You’ve demonstrated how useful it is to catch user error.

No, what I have demonstrated is how EASY is to fall in non-user error.  
And I called first() so that I can still do a test if `output != 0`, which is now also more or less useless because of the `nothing`

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [February 17, 2018, 6:44pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/6 "2018-02-17T18:44:37Z")

</div>

> [@Nosferican](#):
>
> I was used to having it returned 0 and then managing the case. A bit taken by the decision to change this in 0.7.

It is completely valid for an `AbstractArray` to have 0 as a valid index. Then what do you do?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 17, 2018, 6:49pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/7 "2018-02-17T18:49:21Z")

</div>

> [@joa-quim](#):
>
> can still do a test if output != 0

That is the user error. Why do you want to do such a useless test?

---

<div class="post-metadata">

**Author:** ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)\
**Post date:** [February 17, 2018, 6:56pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/8 "2018-02-17T18:56:09Z")

</div>

I wasn’t aware `AbstractArray` supported non \mathbb{N} numbers. I believed it was only possible to index arrays from 1:size(obj, dim). If that is the case, I don’t think `0` was a good previous behavior. Wouldn’t suggest negative index since that might represent `(end - index)` in future versions. In that case, `nothing` seems appropriate and just dispatch on either an `Integer` or `nothing`.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [February 17, 2018, 6:56pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/9 "2018-02-17T18:56:50Z")

</div>

> [@yuyichao](#):
>
> Why do you want to do such a useless test?

julia\> findfirst(“abcd”,“ef”) == 0  
false

julia\> first(findfirst(“abcd”,“ef”)) == 0  
true

Though I see that I can use `isempty()` for this case. But not for

```julia
isempty(nothing)
ERROR: MethodError: no method matching start(::Nothing)
Closest candidates are:
...

```

---

<div class="post-metadata">

**Author:** ![yurivish](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yurivish/32/307_2.png) [@yurivish](https://discourse.julialang.org/u/yurivish)\
**Post date:** [February 17, 2018, 7:00pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/10 "2018-02-17T19:00:58Z")

</div>

For a bit of additional texture on the use cases enabled by more flexible indexing I recommend having a look through the JuliaArrays org: [https://github.com/JuliaArrays](https://github.com/JuliaArrays).

Two particularly good examples of nontraditional but highly useful indexing are [AxisArrays.jl](https://github.com/JuliaArrays/AxisArrays.jl) and [OffsetArrays.jl](https://github.com/JuliaArrays/OffsetArrays.jl).

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 17, 2018, 7:02pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/11 "2018-02-17T19:02:53Z")

</div>

> [@joa-quim](#):
>
> findfirst(“abcd”,“ef”)

That’s not even the same method. It’s not searching for an element in a collection at all so why do you expect it to have exactly the same behavior as searching an array?

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [February 17, 2018, 7:49pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/12 "2018-02-17T19:49:02Z")

</div>

I don’t know much about the `findfirst` usecase for strings as I very rarely do string processing but concerning the element in a collection method, I find the new behavior much better. Returning `0` is not very principled and could lead to issues (for example, if I’m using OffsetArrays, did I find `0` or did I not find anything at all?).

Returning `nothing` has several advantages:

- There can be no confusion as to whether a match was found or not
- One can dispatch on the returned type to decide what to do next
- If desired, it’s easy to replace it with some other value with `coalesce`:

```julia
coalesce(findfirst(equalto(el), v), 0)

```

To simplify checking for nothingness, I wonder whether it’d be helpful to have `isnothing` (analogous to `ismissing`), but it’s also true that `x isa Nothing` isn’t much longer.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [February 17, 2018, 7:51pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/13 "2018-02-17T19:51:45Z")

</div>

> [@piever](#):
>
> I wonder whether it’d be helpful to have isnothing (analogous to ismissing), but it’s also true that x isa Nothing isn’t much longer.

I would also like an `isnothing(x) = x === nothing` in base. It looks silly but I think it would be useful.

---

<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:** [February 17, 2018, 9:46pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/14 "2018-02-17T21:46:04Z")

</div>

> [@joa-quim](#):
>
> Because findfirst can output a boolean a notthing or an iterator and in this later case, an 0:-1 when it finds nothing.

`findfirst` will always just return the index of the first item it finds. If it doesn’t find anything, it returns `nothing`. It just so happens that vectors use integers as their indices, and numbers are iterable pseudo-collections of themselves.

Personally, I find this a lot less dangerous than the previous behavior. Note that returning `0` instead of a valid index doesn’t require any explicit error checking, either, but it might actually _work_ in your computation and lead to silently wrong answers.

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [February 18, 2018, 11:15am UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/15 "2018-02-18T11:15:43Z")

</div>

2 posts were split to a new topic: [Findfirst() with Dict for which nothing is a valid key](https://discourse.julialang.org/t/findfirst-with-dict-for-which-nothing-is-a-valid-key/9141)

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [February 18, 2018, 11:26am UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/16 "2018-02-18T11:26:06Z")

</div>

There appears to be some confusion here about how the `findfirst` methods behave. The standard `findfirst` method operates over elements in a collection and returns the index/key of the first matching element, or `nothing` if no element matches.

Then, there’s the special case of looking for a substring in a string, e.g. `findfirst("ab", "abc")` or `findfirst(r"ab", "abc")`. This method is very different from the general one, since it looks for a sequence of elements (here, characters) in a collection (here, a string). So it returns the range corresponding to the first matching sequence, rather than a single index (indeed, in the case of a regular expression, you don’t know in advance the length of the matching substring so that’s an additional information). If there’s no match, an empty range is returned. We could imagine returning `nothing` instead for consistency.

At any rate, I don’t understand why the OP wants to call `first` on the result of `findfirst(equalto(:z), fieldnames(x))`, given that this function returns a scalar.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [February 18, 2018, 2:08pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/17 "2018-02-18T14:08:02Z")

</div>

> [@nalimilan](#):
>
> At any rate, I don’t understand why the OP wants to call first on the result of findfirst(equalto(:z), fieldnames(x)), given that this function returns a scalar.

Agree, no sense here but I’m the middle of 0.6 to 0.7 transition and in order that same code for strings works I have to call `first(findfirst("abcd","ef"))` to get a scalar that I can compare to 0.

```julia
first(findfirst("abcd","ef")) == 0

```

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [February 18, 2018, 2:24pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/18 "2018-02-18T14:24:01Z")

</div>

> [@joa-quim](#):
>
> Agree, no sense here but I’m the middle of 0.6 to 0.7 transition and in order that same code for strings works I have to call first(findfirst(“abcd”,“ef”)) to get a scalar that I can compare to 0.
> 
> first(findfirst(“abcd”,“ef”)) == 0

If you need this pattern a lot (getting `0` if no element is found/no substring is found, otherwise the element index - for arrays - and the first index of the substring) you may define your own helper function:

```julia
julia> myfirst(n) = first(n)
myfirst (generic function with 1 method)

julia> myfirst(::Nothing) = 0
myfirst (generic function with 2 methods)

julia> map(myfirst, (0:-1, 2:3, 4, nothing))
(0, 2, 4, 0)

```

In principles it does seem a bit more consistent for `findfirst` to return `nothing` rather than the empty range in the substring case, but maybe there are advantages in always returning a range that I’m not seeing.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [February 18, 2018, 3:07pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/19 "2018-02-18T15:07:41Z")

</div>

What I’m not sure of, is how much the compiler would be able to do with this, to get back to the performance it used to have, since it has a dynamic dispatch.

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [February 18, 2018, 4:00pm UTC](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/20 "2018-02-18T16:00:40Z")

</div>

> [@joa-quim](#):
>
> Agree, no sense here but I’m the middle of 0.6 to 0.7 transition and in order that same code for strings works I have to call first(findfirst(“abcd”,“ef”)) to get a scalar that I can compare to 0.
> 
> first(findfirst(“abcd”,“ef”)) == 0

I still don’t get it. On Julia 0.6 `findfirst("ef","ef")` returns `0` since it’s looking for a character equal to `"ef"`. So that doesn’t sound very useful and it’s completely different from what happens on 0.7 (disregarding the question of `nothing`).

Anyway, use `Compat.findfirst` if you want to support both Julia 0.6 and 0.7 using the 0.7 API.

[Next page](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131.md?page=2)
