# Could the usage of \`haskey\` be unidiomatic/inefficient?

**URL:** <https://discourse.julialang.org/t/could-the-usage-of-haskey-be-unidiomatic-inefficient/17442>\
**Category:** Performance\
**Tags:** dictionary\
**Created:** [November 12, 2018, 6:00pm UTC](https://discourse.julialang.org/t/could-the-usage-of-haskey-be-unidiomatic-inefficient/17442 "2018-11-12T18:00:56Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![SZJX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/szjx/32/4036_2.png) [@SZJX](https://discourse.julialang.org/u/SZJX)\
**Post date:** [November 12, 2018, 6:00pm UTC](https://discourse.julialang.org/t/could-the-usage-of-haskey-be-unidiomatic-inefficient/17442/1 "2018-11-12T18:00:56Z")

</div>

It seems to be a common pattern to me that something like this needs to be done:

```julia
if !haskey(dict, key)
  ...
else
  item = dict[key]
  ...
end

```

Would this lead to two lookups and thus cause extra overhead?

I considered using `get/3` but it can only go so far as to provide a default value. In cases where more complicated operations instead of just getting a value is needed, I still need to write

```julia
item = get(dict, key, nothing)
if item == nothing
  # do stuffs
else
  # do stuffs with item
end

```

which still involves an extra comparison operation and doesn’t seem to be sensible code at all.

AFAIK in languages such as Rust there seem to be special constructs that help deal with such cases with a Dict.

What’s the idiomatic way to do so? Or is it just simply not a performance concern due to some sort of optimization, and I shouldn’t worry about using `!haskey` in this scenario?

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [November 12, 2018, 6:03pm UTC](https://discourse.julialang.org/t/could-the-usage-of-haskey-be-unidiomatic-inefficient/17442/2 "2018-11-12T18:03:51Z")

</div>

See [julep/rfc: proposal for unified Dict get/insert/has interface · Issue #12157 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/12157)

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 12, 2018, 6:28pm UTC](https://discourse.julialang.org/t/could-the-usage-of-haskey-be-unidiomatic-inefficient/17442/3 "2018-11-12T18:28:22Z")

</div>

What about

```julia
function dostuff(dict, key)
    found = true
    item = get(() -> found = false, dict, key)
    if found
        Some(item)
    else
        nothing
    end
end

d = Dict([1 => 'a'])
dostuff(d, 1) # Some('a')
dostuff(d, 2) # nothing

```

---

<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:** [November 12, 2018, 6:40pm UTC](https://discourse.julialang.org/t/could-the-usage-of-haskey-be-unidiomatic-inefficient/17442/4 "2018-11-12T18:40:22Z")

</div>

Only you can `Profile.@profile` whether this is a perf problem in your specific code. This does cause two lookups, but the first one will fetch the relevant cache-line. So the second lookup only costs CPU and no mem-traffic nor does it have to wait an eternity for main memory.

If profiling shows that the second lookup is a significant part of your time, then my recommendation is `Base.ht_keyindex2!` (look up position of key; -pos if not present; may rehash dict to make space for new element) and `Base.ht_keyindex` (look up position of key, -1 if not present).

The optimizer might be capable of removing the second hash computation. I don’t think that the optimizer will be capable of removing the comparisons (the linear search of all colliding elements).

---

<div class="post-metadata">

**Author:** ![00vareladavid](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/00vareladavid/32/23521_2.png) [@00vareladavid](https://discourse.julialang.org/u/00vareladavid)\
**Post date:** [November 12, 2018, 10:10pm UTC](https://discourse.julialang.org/t/could-the-usage-of-haskey-be-unidiomatic-inefficient/17442/5 "2018-11-12T22:10:38Z")

</div>

I don’t see what is wrong with:

```julia
item = get(dict, key, nothing)
if item === nothing
  # do stuffs
else
  # do stuffs with item
end

```

Only one lookup and `=== nothing` is fast.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [November 12, 2018, 10:54pm UTC](https://discourse.julialang.org/t/could-the-usage-of-haskey-be-unidiomatic-inefficient/17442/6 "2018-11-12T22:54:25Z")

</div>

The only issue these days is if `nothing` is a valid value. Otherwise that is a fine way to express this in Julia 1.0+.

---

<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:** [November 13, 2018, 1:45am UTC](https://discourse.julialang.org/t/could-the-usage-of-haskey-be-unidiomatic-inefficient/17442/7 "2018-11-13T01:45:01Z")

</div>

You could always just define your own

```julia
struct MySentinel end

```

and use that instead of `Nothing`. There are not specific optimisations for the `nothing` singleton that doesn’t apply to others.
