Using sizehint! on a Dict that I would like to declare const


#1

My understanding of how sizehint! works is that it needs to be called over a Dict before you populate the Dict with key/value pairs, if you want to see any performance benefit. Is this correct?

If so, then it would suggest that if I would like to declare a Dict as a const, then I would need to do the following (for example):

const MY_DICT = Dict{Int,Int}()
sizehint!(MY_DICT, 5)
for i = 1:5
    setindex!(MY_DICT, i=>i+1)
end

The point is that I’m changing my Dict after declaring it const. I can’t see any reason why this would be a problem, since my understanding of const is that it is for fixing the type, rather than the value. Basically, I just wanted to check if my understanding is correct here and that I’m not doing something stupid by adding to the Dict after declaring it const.

Note, related Discourse post here which maybe suggests that changing the Dict after declaring it const might affect how it works in in-lined code - although I note that there are no redefinition warnings when inserting new key/value pairs.

Cheers,

Colin


#2

A dictionary is a container, and you can add or remove elements from that container without changing the identity of the container. So there’s no problem at all declaring a Dict const and then adding elements to it and/or calling sizehint!().

This is different than the post you linked to, which refers to binding an entirely new value to the const variable and is not OK.

The difference is between modifying the contents of a dictionary and replacing it with a new object. So, this is fine:

const d = Dict{Int, Int}()
d[1] = 2

but this is not:

const d = Dict{Int, Int}()
d = Dict{Int, Int}(1 => 2)

There’s nothing special about Dict here. The same argument applies to any mutable object or object that contains some mutable data.

Another way of thinking about this is asking what happens if you put a Dict inside an immutable struct:

julia> struct Container
         d::Dict{Int, Int}
       end

julia> c = Container(Dict{Int, Int}())
Container(Dict{Int64,Int64}())

julia> c.d[1] = 2  # this is fine. We are not changing the identity of `c.d`, just putting some new data inside it
2

julia> c.d = Dict(1 => 2)  # this doesn't work
ERROR: type Container is immutable

#3

That is very clear thank you. My intuition was that it worked like that, but then what I read in that other post threw me a little. But relating it to mutability and immutability makes it very obvious what is allowed and what isn’t.

Cheers,

Colin