function poprand!(v)
"""Remove random variable from vector v"""
return splice!(v, rand(1:length(v)))
end
begin
inputs = collect(1:4)
results = Dict{Vector{Int64}, Float64}()
for _ in 1:5
inputs = collect(sort(tuple(inputs...)))
results[inputs] = rand(1:100)
@assert haskey(results,inputs)
poprand!(inputs)
push!(inputs, rand(1:100))
end
end
haskey(results,collect(keys(results))[1]) # false
The hash value used to put the entry in the dictionary is computed from the key, and that does not change when you mutate the key. When you index with an equal value, it computes a different hash value and fails to find the key.
I wondered about mutation but when viewing keys(results) and hash.(keys(results)) each value was unique whereas I thought this issue would mean all entries would mean there would be duplicates in hash/key (although this doesn’t make sense now I think about it).
However, adding a copy to the key (results[copy(inputs)] =...) makes the example work, so you’re right it is mutating keys.
But this copy based solution doesn’t seem ideal. Is there a better way?
Depends on what you mean with “better”. Using mutable values as keys and mutating them is inherently not good, so the only other option is to keep the old object around, so that you can access the value stored in the Dict later again. By definition, if you use a different object as a key, you’re going to get a different or no value at all.
Can you perhaps reword your algorithm, so that it doesn’t require storing mutable objects in a dictionary?