Suppose I want to define a vararg method for Base.* which is invoked when at least one argument is of a given type Foo (for the purposes of this discussion, struct Foo end suffices).
What’s the recommended way of doing that? Is there a possibility to do it in a way that composes with other packages that do something similar?
If you don’t mind defining a ton of methods and can put a reasonable guess on the maximum number of args you need to support, you can use metaprogramming to do so.
Thanks! That’s what I suspected from looking at the way various packages deal with the question.
IMO the ideal approach would be traits, along the lines of
# generic code
promote_f_type(::Type{T}, ::Type{S}) where {T,S} = T # the default is: whichever came first
traited_f(::Type, args...) = :the_default
function f(args...)
T = mapfoldl(typeof, promote_f_type, args)
traited_f(T, args...)
end
# type-specific extension
struct Foo end
promote_f_type(::Type{Foo}, ::Type) = Foo
promote_f_type(::Type, ::Type{Foo}) = Foo
traited_f(::Type{Foo}, args...) = :Foo_dominates
If the argument types otherwise differ, won’t that be caught in the promotion machinery? You could try to hook/use that to get a known-to-you wrapper to dispatch on, though it’s not exactly a pretty solution.