Why do functions whose arguments are named tuples fail when one element of the named tuple has type Any?

I defined a function that prints the elements of a named tuple. I do not
know the type of the second element of the named tuple, so I set it to Any.

function foo(nt::NamedTuple{(:A, :V), Tuple{String, Any}})
    println(A * " " * string(V))

Why does this function generate an error?

julia> foo((A = "Hello", V = 1))
ERROR: MethodError: no method matching foo(::NamedTuple{(:A, :V), Tuple{String, Int64}})
Closest candidates are:
  foo(::NamedTuple{(:A, :V), Tuple{String, Any}}) at REPL[1]:1
 [1] top-level scope

How can I fix it so that it works for V of any type?

To fix the dispatch you can do this:

julia> function foo(nt::NamedTuple{(:A, :V), Tuple{A,V}}) where {A,V}

But with your function body you will still get an error, because, in your original definition A and V are not defined. With my correction A and V are types which will error now in your println call.

So I guess what you want to do with this examples:

function foo(nt::NamedTuple{(:A, :V), Tuple{A,V}}) where {A,V}
    println( string(nt[:A]) * " is type " * string(A) * " and " * string(nt[:V]) * " is type " * string(V) )
julia> foo((A = "Hello", V = 1))
Hello is type String and 1 is type Int64

julia> foo((A = "Hello", V = 1.0))
Hello is type String and 1.0 is type Float64

julia> foo((A = "Hello", V = "world"))
Hello is type String and world is type String
1 Like

There is no matching method because type parameters are invariant in Julia. So, just because Int64 <: Any does not mean

julia> NamedTuple{(:A, :V), Tuple{String, Int64}} <: NamedTuple{(:A, :V), Tuple{String, Any}}

To print the values of a NamedTuple as a single string, a simple option is

julia> foo(x::NamedTuple) = join(values(x), " ")

julia> foo((A = "Hello", V = 1))
"Hello 1"

julia> foo((a=Dict(:x=>1), b="bar"))
"Dict(:x => 1) bar"

Thanks. Now I see that I needed to do nt[:A] instead of just A in the call to println. And similarly for V.