# Findfirst() with Dict for which nothing is a valid key

**URL:** https://discourse.julialang.org/t/findfirst-with-dict-for-which-nothing-is-a-valid-key/9141
**Category:** Internals & Design
**Created:** [February 18, 2018, 12:32am UTC](https://discourse.julialang.org/t/findfirst-with-dict-for-which-nothing-is-a-valid-key/9141 "2018-02-18T00:32:10Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)
#### Post date: [February 18, 2018, 12:32am UTC](https://discourse.julialang.org/t/findfirst-with-dict-for-which-nothing-is-a-valid-key/9141/1 "2018-02-18T00:32:10Z")

</div>

Well, it does have the slight problem:

```julia
d=Dict(); d[1]=1; d[nothing]=2;
d
#Dict{Any,Any} with 2 entries:
# nothing => 2
# 1 => 1

@show findfirst(equalto(0), d)
#findfirst(equalto(0), d) = nothing
@show findfirst(equalto(1), d)
#findfirst(equalto(1), d) = 1
@show findfirst(equalto(2), d)
#findfirst(equalto(2), d) = nothing

```

---

<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, 12:38am UTC](https://discourse.julialang.org/t/findfirst-with-dict-for-which-nothing-is-a-valid-key/9141/2 "2018-02-18T00:38:27Z")

</div>

> [@The new output of findfirst is dangerous](https://discourse.julialang.org/t/the-new-output-of-findfirst-is-dangerous/9131/12):
>
> There can be no confusion as to whether a match was found or not

That’s not true, if `nothing` can be an index (key) into the collection.  
All the change did was hurt performance and move the place where things break down from one place (where 0 might be a valid index [now possible with `OffsetArrays`, or other `AbstractArrays`)

I think a better interface, that would not lose any performance, and would be able to handle the case of `nothing` being an index (where I worked we actually used that, to store `JSON` `null` as a key in `AssociativeArrays`s), would be to add two functions, `found(collection, retval)` and `found_key(collection, retval)` (and maybe a macro to make life a bit easier).  
If a particular type can use something like `0`, or `typemin(Int)` as a in-band sentinel value for a not-found index/key, for example with `String`, then you’d have the definition: `found(::Type{String}, val) = val != 0` and `found_key(::Type{String}, val) = val`.  
For something where no in-band sentinel value is possible (i.e. the key is `<: Any`, or any union that includes `Nothing`), then the return value can simply be a tuple, i.e. `(true, value)` or `(false, nothing)`. If `nothing` is found, it would return `(true, nothing)`, and everything works correctly, no funky special cases. The definitions then would be `found(::Type{MyType}, ret) = ret[1]`, and `found_key(::Type{MyType}, ret) = ret[2]`.

---

<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:17am UTC](https://discourse.julialang.org/t/findfirst-with-dict-for-which-nothing-is-a-valid-key/9141/3 "2018-02-18T11:17:01Z")

</div>

See also previous discussion at [Suggestion for more general/performant sentinel for find\* functions - #4 by ScottPJones](https://discourse.julialang.org/t/suggestion-for-more-general-performant-sentinel-for-find-functions/8657/4).
