Let's say I have a function that expects an dict as input. Within that, this function can only handle values of that dict that are in a certain Union
of allowed types. For this argument, the input can be Number
, String
, or Bool
:
allowed_types = Union{String, Int, AbstractFloat, Bool}
The function can also permit Dicts whose values are these allowed types (Dict{String,allowed_types}
) or Arrays whose items are these types (Array{allowed_types,Int}
) as they can be "disassembled" down in to one of those allowed types. (This can keep continuing downwards - so an array of arrays, etc)
full_allowed_types = Union{allowed_types, Dict{String,allowed_types}, Array{allowed_types,Int}}
I can then define my function as
function my_func(input::Dict{String,full_allowed_types})
...
end
How, then, do I structure my function arguments so that I can pass, I.E, my_func(Dict("a"=>"astr","b"=>1))
? Normally that Dict(...)
call results in a Dict{String,Any}
, which doesn't work to call with my function as Any
is not an allowed type.
The error I get with my current implementation is:
my_func(Dict("a"=>"astr","b"=>1))
ERROR: MethodError: no method matching my_func(::Dict{String,Any})
Closest candidates are:
my_func(::Dict{String,Union{Bool, Int64, Dict{String,Union{Bool, Int64, AbstractFloat, String}}, AbstractFloat, Array{Union{Bool, Int64, AbstractFloat, String},Int64}, String}}) at <snip>/my_func.jl:41
Stacktrace:
[1] top-level scope at none:0
I'm picturing this issue from a user standpoint, where the user would likely just create a dict using the default constructor, without considering what my_func
wants to be "allowed" (meaning I don't expect them to call Dict{String,my_pkg.full_allowed_types}(...)
).
Is the best option to just allow Any
as the input to my_func
and then throw an error if any of the elements don't fit with my allowed types as I iterate through the input?
function f(a::Dict{String, A}) where A <: Union{Int,String}
println("Got elem type $A")
end
Usage:
julia> f(Dict{String,Union{String,Int}}("a"=>"astr","b"=>1))
Got elem type Union{Int64, String}
Now if you want to make it convenient for a user you could add an additional function (However, the type conversion will come at a cost):
function f(a::Dict{String,A}) where A
@warn "Provided unsupported type of elements $A will try narrow it to Union{Int,String}"
f(Dict{String,Union{Int,String}}(d))
end
Example usage:
julia> f(Dict("a"=>"astr","b"=>1))
ā Warning: Provided unsuported type of elements Any will try narrow it to Union{Int,String}
ā @ Main REPL[31]:2
Got elem type Union{Int64, String}