How using push on typed dictionary

Hello everybody, i was playing with dictionary … i can’t understand why the last my statement is not correct in this case:


println("1° dictionary")
myDictionary1 = Dict()
push!(myDictionary1,"alpha"=>[10,20]) # ok this works, using push

println("2° dictionary")
myDictionary2 = Dict{String,Vector{Int64}}
myDictionary2("betha"=>[1,2,3,4,5]) # another possible way to add to dictionary
println("2° dictionary using push")
push!(myDictionary2,"alpha"=>[10,20]) # why this gives an error???

I was trying to be more precise in type definition of my Dict, and i tried to transform Dict() in Dict{String,Vector{Int64}}, but, surprisingly, Julia tell me that the last line is not correct, also if in the exact sintex i used in the first dictionary. The error is:


ERROR: LoadError: MethodError: no method matching push!(::Type{Dict{String,Array{Int64,1}}}, ::Pair{String,Array{Int64,1}})
Closest candidates are:
  push!(::Any, ::Any, ::Any) at abstractarray.jl:2159
  push!(::Any, ::Any, ::Any, ::Any...) at abstractarray.jl:2160
  push!(::Array{Any,1}, ::Any) at array.jl:875
  ...
Stacktrace:
 [1] top-level scope at C:\vmswap\juliaPrj\querere\example01.jl:9
in expression starting at C:\vmswap\juliaPrj\querere\example01.jl:9

Thanks for help! i really don’t understand …

There is () missing, you are trying to call push! on a type, not an instance.
Error message is quite clear here I think. Any ideas to improve it?

1 Like

maybe defining an instance of push!(a::AbstractDict,x::Any) would help,other option is to add a verification when a function is called on a type instead of an instance of that type and print an adequate explanation. for example:

ERROR: LoadError: MethodError: no method matching push!(::Type{Dict{String,Array{Int64,1}}}, ::Pair{String,Array{Int64,1}})
Closest candidates are:
  push!(::Any, ::Any, ::Any) at abstractarray.jl:2159
  push!(::Any, ::Any, ::Any, ::Any...) at abstractarray.jl:2160
  push!(::Array{Any,1}, ::Any) at array.jl:875
  ...
Posible problems include:
  -The function was called with a type instead of an instance of said type.
Stacktrace:
 [1] top-level scope at C:\vmswap\juliaPrj\querere\example01.jl:9
in expression starting at C:\vmswap\juliaPrj\querere\example01.jl:9
1 Like

Good idea, generating additional message in such case would be useful. Anyway, this case is really tricky, as this syntax looks like addition really works, but constructor was called instead. Quite funny case, thanks for sharing @Darione .

1 Like

Hi all … I still do not understand well …

This works:

println("2° dictionary")
myDictionary2 = Dict{String,Vector{Int64}}
myDictionary2("betha"=>[1,2,3,4,5])

This other doesn’t:

println("3° dictionary")
myDictionary3 = Dict{String,Vector{Int64}}
push!(myDictionary3,"alpha"=>[10,20])     

How exactly should be the last line, using push! ? or is myDictionary3 = … that i have to change in another way, to have an instance and not a type ?

Many thanks :slight_smile:

In the case of myDictionary3, you cannot push a key-value pair into a Type. You need to instantiate by calling the constructor, with() at the end:

myDictionary3 = Dict{String,Vector{Int64}}()

Without the (), myDictionary3 is just an alias for Dict{String,Vector{Int64}}. A similar example would be INT = Int64. Here I simply created the alias INT for the Int64 Type (it is not a variable containing some Int value). This means that if I wanted to convert a float to int I could use INT(2.0) instead of Int64(2.0), and it would work the same.

In the case of myDictionary2, you call the constructor directly with the line myDictionary2("betha"=>[1,2,3,4,5])

See:
Introducing Julia/Dictionaries and sets - Wikibooks, open books for an open world, at " More complex structures" section

2 Likes

Ahhhhhh, now I understand, thank you very much @Iulian.Cioarca !
I will read with attention the link you copy me.
I rember to have read the type redefinition one time … i will read again.

1 Like

Another question related to this.

If I want to be, as in that case, precise on the type of dictionary I need (writing Dict{String,Vector{Int64}}() instead of simply Dict() ) , it will get a benefit in terms of speed of execution of the code, or, in your opinion, it is irrelevant because, in short, Julia understands the type of dictionary I serve and do you fill in?

I tried in a for loop, where in every iteration I define a dictionary of tens of thousands of string keys, trying both the use of Dict () and the one with the precise type I need, and it seems to me that nothing changes in terms of speed of execution. It’s correct? or i should see a gain in speed if i define exacty the type?

Thank you very much for help to make me undestand the best way to use Julia.

I havent checked, but if you create a dict directly with the keys, the types are inferred automatically from the key value pairs, so it’s not necessary when you create dicts with keys inside.
it’s relevant when you create empty dicts, as without keys, the diccionary does not have any information to create an appropriate structure, and defaults to the slow type Any

1 Like