Understanding Dict

Hi everyone.

I am coming from python background. In python, dictionary keys cannot be mutable because it is based on hash table. However, keys in Dict in julia do not need to be immutable. I wonder how this is achieved?

mutating keys in a way that changes the hash is undefined.

Translation: Python protects the user from him/herself. Julia lets you shoot yourself in the foot. :smiley: (Basically, if a programmer uses a mutable as a key in a Dict, she needs to know to not mutate it in a way that changes the hash, as @yuyichao pointed out.)

Cheers!

Kevin

1 Like

Then why this works?

julia> d = Dict()
Dict{Any,Any} with 0 entries

julia> a = [1, 2, 3]
3-element Array{Int64,1}:
 1
 2
 3

julia> d[a] = "test"
"test"

julia> a[1] = 4
4

julia> d
Dict{Any,Any} with 1 entry:
  [4, 2, 3] => "test"

Hash of an array is not related to its content?

Here is your test case with one additional instruction to show that d is actually broken:

julia> d = Dict()
Dict{Any,Any} with 0 entries

julia> a = [1,2,3]
3-element Array{Int64,1}:
 1
 2
 3

julia> d[a] = "test"
"test"

julia> a[1] = 4
4

julia> d
Dict{Any,Any} with 1 entry:
  [4, 2, 3] => "test"

julia> d[a]
ERROR: KeyError: key [4, 2, 3] not found
Stacktrace:
 [1] getindex(::Dict{Any,Any}, ::Array{Int64,1}) at .\dict.jl:474

It “works” because the table is maintaned and allows Base.show to function, but other things break because d will be in an inconsistent state. Try eg d[a].

Also, there is a distinction between “not guaranteed to work” and “guaranteed to break”. The latter was not implied.

Right, and that’s what undefined means. The language/compiler/whatever can do whatever it want after something undefined happens. It can pretend things still works or it can crash randomly or it can silently fix itself later.

Thank you.

I have another question though: Are keys of ObjectIdDict guaranteed not to be garbage collected?

Anything you can access as an object in julia will not be garbage collected. This certainly include keys of ObjectIdDict but not when you get a pointer to the object by pointer_from_objref.

This isn’t true of Python. It will certainly also let you define invalid hash functions with the same undefined (and generally memory-safe) behaviors as Julia.