Not knowing the context, this may not be helpful, but: Since you mention dispatch, I infer that you are trying to find out which method (signature) is called for a given input combination. @which may help:
julia> foo(x :: Union{Float64,Int}) = 1
foo (generic function with 1 method)
julia> foo(x :: String) = 2
foo (generic function with 2 methods)
julia> meth = @which foo(1)
foo(x::Union{Float64, Int64}) in Main at REPL[2]:1
julia> meth.sig
Tuple{typeof(foo), Union{Float64, Int64}}
Thanks for the responses, I think i didn’t make myself clear enough. So i’ll give some extra information.
What i’m looking for is to do “rule-based transformation”. I want to transform the input to some output dependent on some rules. Think of f1… f4 in the seocnd part of the question as the rules.
The problem is that I also want to be able to add and remove rules based on user input. Thus dispatch with a function is not enough as removing rules wouldn’t be possible then.
A solution to any of the 2 questions would allow me to build such a system.
Simply finding the first type signature that matches is fairly straightforward:
types_match(input, possible) = all(input .<: possible)
types_match(input) = possible -> types_match(input, possible)
function would_dispatch_to(input, possibles)
i = findfirst(types_match(input), possibles)
i ≡ nothing && return nothing
return possibles[i]
end
Assuming your use-case is fairly simple this should be fine but the actual dispatch algorithm that Julia uses is more complicated than this. In particular, the way that you build your possible_argument_types is crucial, as well as detecting when you have ambiguous/overlapping definitions.
For future reference, I got it to work AFAIK starting from your solution. This one accounts for multiple possible matches.
types_match(input, possible) = all(input .<: possible)
function would_dispatch_to(input_sig, d::Set)
input_sig in d && return input_sig
most_specific = nothing
equaly_specific = Any[]
for sig in d
if types_match(input_sig, sig)
if most_specific === nothing
most_specific = sig
else
if types_match(sig, most_specific)
most_specific = sig
empty!(equaly_specific)
elseif !types_match(most_specific, sig) #test for ambiguity
push!(equaly_specific, sig)
end
end
end
end
length(equaly_specific) > 0 && error("MethodError: $input_sig is ambiguous. The candidates are:\n\t$(mapreduce(identity, (a,b)-> (string(a)*"\n\t"*string(b)), (most_specific, equaly_specific...)))")
most_specific === nothing && error("MethodError: no method matching $input_sig")
most_specific
end
possible_argument_types = Set([(Int,), (Int,Union{Real,Char}), (Float64,Int), (Any,Int)])
input_type = (String,Int)
would_dispatch_to(input_type, possible_argument_types)