# keys() potential bug?

**URL:** <https://discourse.julialang.org/t/keys-potential-bug/15424>\
**Category:** General Usage\
**Created:** [September 24, 2018, 11:23am UTC](https://discourse.julialang.org/t/keys-potential-bug/15424 "2018-09-24T11:23:41Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![alin314](https://avatars.discourse-cdn.com/v4/letter/a/839c29/32.png) [@alin314](https://discourse.julialang.org/u/alin314)\
**Post date:** [September 24, 2018, 11:23am UTC](https://discourse.julialang.org/t/keys-potential-bug/15424/1 "2018-09-24T11:23:41Z")

</div>

Running the following code:

s = Dict(1=\>‘a’, 2=\>‘b’)  
for key in keys(s)  
println(key)  
s[key+1] = ‘x’  
end

generates the result:  
2  
3  
1

Is this a bug? I expect the result to contain only keys 1 and 2. If I replace keys(s) with collect(keys(s)), I get the correct result.

I have:  
Julia Version 1.0.0  
Commit 5d4eaca0c9 (2018-08-08 20:58 UTC)  
Platform Info:  
OS: Linux (x86\_64-pc-linux-gnu)  
CPU: Intel(R) Core™ i5-8250U CPU @ 1.60GHz  
WORD\_SIZE: 64  
LIBM: libopenlibm  
LLVM: libLLVM-6.0.0 (ORCJIT, skylake)

Thanks!

---

<div class="post-metadata">

**Author:** ![JonasIsensee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jonasisensee/32/4704_2.png) [@JonasIsensee](https://discourse.julialang.org/u/JonasIsensee)\
**Post date:** [September 24, 2018, 11:40am UTC](https://discourse.julialang.org/t/keys-potential-bug/15424/2 "2018-09-24T11:40:43Z")

</div>

I would say that this is not a bug.  
AFAICT `keys` is a lazy iterator.  
That means that `for key in keys(s)` does not compute a list of all valid keys and _then_  
executes the loop but rather computes the next key(s) on the fly.  
Since you keep adding elements to your dictionary, you end up with more unintended iterations.

Another example:

```julia
x = [0]
for el in x
    push!(x, el+1)
    println(el)
end

```

This gives you an infinite loop. In every iteration a new element has been added.

In general I would say that it is a bad idea to modify the iterator inside the for loop.  
Your `collect(keys(s))` is better.

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [September 24, 2018, 11:48am UTC](https://discourse.julialang.org/t/keys-potential-bug/15424/3 "2018-09-24T11:48:03Z")

</div>

The line `s[key+1] = 'x'` is extending the dictionary as you go through the loop.

to see this better

```julia

julia> dict = Dict(1 => "1", 2 => "2")
Dict{Int64,String} with 2 entries:
  2 => "2"
  1 => "1"

julia> for k in keys(dict)
           println( keys(dict) )
           dict[k+1] = string(k+1)
           println("dict keys: $(keys(dict))")
       end
[2, 1]
dict keys: [2, 3, 1]
[2, 3, 1]
dict keys: [4, 2, 3, 1]
[4, 2, 3, 1]
dict keys: [4, 2, 3, 1]

```

---

<div class="post-metadata">

**Author:** ![alin314](https://avatars.discourse-cdn.com/v4/letter/a/839c29/32.png) [@alin314](https://discourse.julialang.org/u/alin314)\
**Post date:** [September 24, 2018, 3:47pm UTC](https://discourse.julialang.org/t/keys-potential-bug/15424/4 "2018-09-24T15:47:39Z")

</div>

Mm… It is counter-intuitive, isn’t it? Are we asking users to play computers, to be operational? What is the semantic definition of keys()? I am thinking from the point of view of language design.

Is it possible to design the iterators not to include the new keys? If not, maybe the documentation can help by emphasize the operational nature of keys() in the dictionary section and for iterators in general.

Thanks.

---

<div class="post-metadata">

**Author:** ![anon94023334](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@anon94023334](https://discourse.julialang.org/u/anon94023334)\
**Post date:** [September 24, 2018, 4:39pm UTC](https://discourse.julialang.org/t/keys-potential-bug/15424/5 "2018-09-24T16:39:11Z")

</div>

> [@alin314](#):
>
> Mm… It is counter-intuitive, isn’t it?

I don’t think so. If you modify an iterator within the loop, all sorts of strange things can happen. This applies to all languages.

If you don’t want this, then `collect(keys(..))` should be used to generate a non-lazy iterator:

```julia
julia> for key in collect(keys(s))
       println(key)
       s[key+1] = 'x'
       end
2
1

julia> s
Dict{Int64,Char} with 3 entries:
  2 => 'x'
  3 => 'x'
  1 => 'a'

```

---

<div class="post-metadata">

**Author:** ![alin314](https://avatars.discourse-cdn.com/v4/letter/a/839c29/32.png) [@alin314](https://discourse.julialang.org/u/alin314)\
**Post date:** [September 24, 2018, 4:47pm UTC](https://discourse.julialang.org/t/keys-potential-bug/15424/6 "2018-09-24T16:47:46Z")

</div>

> [@anon94023334](#):
>
> If you modify an iterator within the loop, all sorts of strange things can happen.

Here is another example:

s = Dict(1=\>‘a’)  
for key in keys(s)  
println(key)  
s[key+1] = ‘x’  
end

This time only the key 1 is printed. I have to agree with the statement “If you modify an iterator within the loop, all sorts of strange things can happen.” 😉
