DataStructures.jl
DataStructures.jl copied to clipboard
Set Empty DefaultDict to new struct object may leads to pass by copy
Based on my tests using the DataStructures package, if you create a new DefaultDict
empty and pass it to your new object it does not pass by reference but by copy and this leads to strange behaviour (imho). This is very subtle for me and should give some error or warning when you try.
SIMULATE THE ISSUE
1. Create Empty DefaultDict
julia> using DataStructures
julia> a = DefaultDict(0)
DefaultDict{Any, Any, Int64}()
2. Create your struct as dict
julia> struct D1
data::Dict
end
3. Assign the default dict to your object
julia> d = D1(a)
D1(Dict{Any, Any}())
4. Update initial default dict
julia> a["A"] = 1
1
5. Check the object and you will see that it was not updated as expected
julia> d.data
Dict{Any, Any}()
HOW TO AVOID THIS BEHAVIOUR
Basically in the data struct instead of using a Dict
object use AbstractDict
and the issue will not happen. But I think for me this creates some inconsistency in the code. What we should do?
julia> using DataStructures
julia> a = DefaultDict(0)
DefaultDict{Any, Any, Int64}()
julia> struct D2
data::AbstractDict
end
julia> d = D2(a)
D2(DefaultDict{Any, Any, Int64}())
julia> a["A"] = 1
1
julia> d.data
DefaultDict{Any, Any, Int64} with 1 entry:
"A" => 1
The following is a quote from the manual: (https://docs.julialang.org/en/v1/manual/conversion-and-promotion/#When-is-convert-called?)
convert(T, x)
is expected to return the original x
if x
is already of type T
. In contrast, if T
is a mutable collection type then T(x)
should always make a new collection (copying elements from x
).
So I think the behavior you have observed is expected.