Method Error : Not identifying Integer as Any

Hi, I have function update_agent_attributes that accepts a Dict{Symbol, Any} as one of the arguments. However when I pass a Dict{Symbol, Interger} I get an Method Error. Any idea why ?

mutable struct Casualty
    id :: Int 
    pos :: Tuple{Int,Int}
    trauma :: Int 
    awaiting_rescue :: Bool
    rescued_by :: Int
end

mutable struct Rescuer
    id :: Int 
    pos :: Tuple{Int, Int}
end

@doc "Update agent attributes" ->
function update_agent_attributes!(agent::Union{Casualty,Rescuer},attr::Dict{Symbol,Any})
    for (k,v) in attr
        setfield!(agent,k,v)
    end 
end

c1 = Casualty(1, (7,7), 3, true, 999)
attrs = Dict(:awaiting_recue => false, :rescued_by => 6)
update_agent_attributes!(c1, attrs)

>>>
ERROR: MethodError: no method matching update_agent_attributes!(::Casualty, ::Dict{Symbol, Integer})
Closest candidates are:
  update_agent_attributes!(::Union{Casualty, Rescuer}, !Matched::Dict{Symbol, Any}) at ~/github/CRTT-lite/crtt_lite_osm.jl:120

A smaller MWE would be

julia> f(d::Dict{Int, Any}) = println(keys(d))

julia> f(Dict(1=>1, 2=>"a"))
[2, 1]

julia> f(Dict(1=>1, 2=>2))
ERROR: MethodError: no method matching f(::Dict{Int64, Int64})
Closest candidates are:
  f(::Dict{Int64, Any}) at REPL[3]:1
Stacktrace:
 [1] top-level scope
   @ REPL[4]:1

what you actually want is

julia> g(d::Dict{Int, T}) where T <: Any  = println(keys(d))
g (generic function with 1 method)

julia> g(Dict(1=>1, 2=>"a"))
[2, 1]

julia> g(Dict(1=>1, 2=>2))
[2, 1]

As although Any sounds general, it is, in f's context, a specific type of Dict, so only one method will be created - one that unboxes the Any of the values.

Whereas in g's context, a method for each type T can be generated specialised on the type of T.

3 Likes

Alternatively

g(d::Dict{Int, <:Any}) = println(keys(d))
2 Likes

In essence, this comes down to parametric types in julia being invariant, not covariant. So even though we have Int <: Any we DO NOT have Foo{Int} <: Foo{Any}.

1 Like