# Shouldn't \`findfirst\` propagate \`missing\` instead of erroring?

**URL:** <https://discourse.julialang.org/t/shouldnt-findfirst-propagate-missing-instead-of-erroring/82569>\
**Category:** Internals & Design\
**Created:** [June 10, 2022, 3:30pm UTC](https://discourse.julialang.org/t/shouldnt-findfirst-propagate-missing-instead-of-erroring/82569 "2022-06-10T15:30:06Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [June 10, 2022, 3:30pm UTC](https://discourse.julialang.org/t/shouldnt-findfirst-propagate-missing-instead-of-erroring/82569/1 "2022-06-10T15:30:06Z")

</div>

The whole idea of `missing` vs `nothing` is that the first one should propagate but not erroring, but then:

```julia
a = findfirst(x -> x == 1, [1,0,missing, 1]) # out: 1, ok
b = findfirst(x -> x == 1, [0,0,missing, 1]) # out: error, should be `missing`
c = findfirst(x -> x == 1, [0,0,missing, 0]) # out: error, should be `missing`

```

---

<div class="post-metadata">

**Author:** ![contradict](https://avatars.discourse-cdn.com/v4/letter/c/ac91a4/32.png) [@contradict](https://discourse.julialang.org/u/contradict)\
**Post date:** [June 10, 2022, 3:47pm UTC](https://discourse.julialang.org/t/shouldnt-findfirst-propagate-missing-instead-of-erroring/82569/2 "2022-06-10T15:47:37Z")

</div>

You need to use `skipmissing` to get that behavior.

```julia
julia> findfirst(x -> x == 1, skipmissing([0,0,missing, 0]))

julia> findfirst(x -> x == 1, skipmissing([0,0,missing, 1]))
4

```

---

<div class="post-metadata">

**Author:** ![dmolina](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmolina/32/5246_2.png) [@dmolina](https://discourse.julialang.org/u/dmolina)\
**Post date:** [June 10, 2022, 3:50pm UTC](https://discourse.julialang.org/t/shouldnt-findfirst-propagate-missing-instead-of-erroring/82569/3 "2022-06-10T15:50:04Z")

</div>

Yes, sometimes it is confusing.

`==` does not work nicely with missing, but you can use `isequal`, that works as you could expect:

You could do

```julia
a = findfirst(x->isequal(x, 1), [1, 0, missing, 1]) # out: 1, ok
b = findfirst(x->isequal(x, 1), [0, 0, missing, 1]) # out: 4, ok
c = findfirst(x->isequal(x, 1), [0, 0, missing, 0]) # out: nothing

```

or even:

```julia
a = findfirst(isequal(1), [1, 0, missing, 1])
...

```

---

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [June 10, 2022, 3:56pm UTC](https://discourse.julialang.org/t/shouldnt-findfirst-propagate-missing-instead-of-erroring/82569/4 "2022-06-10T15:56:04Z")

</div>

Thank you. However both solutions return `nothing` with `[0,0,missing,0]`, while I think `missing` should be more appropriate, as we don’t know the 3rd value.

This “manual version” of `findfirst` works but it is ugly and possibly very slow:

```julia
function findfirst_custom(f,x)
    for i in 1:length(x)
        if ismissing(x[i])
            return missing
        elseif f(x[i]) == true
            return i
        end
    end
    return nothing
end

```

EDIT: not too slower, at least for these simple cases:

```julia
small = [0,0,0,1]
long = append!(fill(0,100000),[1,0])
@btime findfirst(x -> x == 1, $small) # 4.864 ns (0 allocations: 0 bytes)
@btime findfirst_custom(x -> x == 1, $small) # 4.873 ns (0 allocations: 0 bytes)
@btime findfirst(x -> x == 1, $long) # 77.870 μs (0 allocations: 0 bytes)
@btime findfirst_custom(x -> x == 1, $long) # 89.216 μs (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [June 10, 2022, 4:10pm UTC](https://discourse.julialang.org/t/shouldnt-findfirst-propagate-missing-instead-of-erroring/82569/5 "2022-06-10T16:10:41Z")

</div>

Why do you think it would be slow? It looks close to optimal to me, except you should of course not use `1:length(x)` but `pairs`.

(Also, it is redundant to test for `== true`).

---

<div class="post-metadata">

**Author:** ![dmolina](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmolina/32/5246_2.png) [@dmolina](https://discourse.julialang.org/u/dmolina)\
**Post date:** [June 10, 2022, 4:30pm UTC](https://discourse.julialang.org/t/shouldnt-findfirst-propagate-missing-instead-of-erroring/82569/6 "2022-06-10T16:30:43Z")

</div>

Following the suggestions from @DNF,

```julia
function findfirst_custom(f,x)
          for (i,val) in pairs(x)
               if ismissing(val)
                   return missing
               elseif f(val)
                   return i
               end
           end
           return nothing
       end

```

In my computer it takes not slower than findfirst, test it.

---

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [June 10, 2022, 4:41pm UTC](https://discourse.julialang.org/t/shouldnt-findfirst-propagate-missing-instead-of-erroring/82569/7 "2022-06-10T16:41:12Z")

</div>

yes. Any how, it would be enough to add some `ismissing(A[i]) && return missing` to some functions (`findnext`…) in [⋅]/base/array.jl

Would it make sense to you? (moving to Internal & Design)

---

<div class="post-metadata">

**Author:** ![halleysfifthinc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/halleysfifthinc/32/206280_2.png) [@halleysfifthinc](https://discourse.julialang.org/u/halleysfifthinc)\
**Post date:** [June 10, 2022, 5:51pm UTC](https://discourse.julialang.org/t/shouldnt-findfirst-propagate-missing-instead-of-erroring/82569/8 "2022-06-10T17:51:18Z")

</div>

As I understand, `missing` should propagate to the same type/data (conceptually). `findfirst` isn’t returning an element of the input array, but the _index_ of an element in the input array.

`b = findfirst(x -> x == 1, [0,0,missing, 1])` producing an error has the fewest assumptions about what the correct behavior is (and allows the user to specify their desired behavior/solution, e.g. `skipmissing` or an `isequal` predicate). The documented behavior of `findfirst` is to return a valid index/key or `nothing` if no element matches the predicate. A result of `missing` wouldn’t make sense to me, as an index exists or does not exist; there is no such thing as a `missing` index, IMO.

---

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [June 10, 2022, 7:24pm UTC](https://discourse.julialang.org/t/shouldnt-findfirst-propagate-missing-instead-of-erroring/82569/9 "2022-06-10T19:24:38Z")

</div>

I disagree on your last sentence 🙂 : an index exists, it doesn’t or I don’t know if it does exists (or which is it, when missing comes before a value for which I have true in the inner function)
