Say that we have two types:
struct A end #= other library =#
struct B end #= my library =#
Now, let’s assume that in some other library there is a method:
foo(x, xs...) = 1
foo(x::A, xs::A...) = 1
I want to overload this method to return 2, for situations where any of (x, xs...) is type B.
In theory, this should be valid in the method hierarchy, right? I just can’t figure out how to actually express it. Is there a way I can do this without causing ambiguities or committing piracy?
So far I have been doing
foo(x::B, xs...) = 2
foo(x, x2::B, xs...) = 2
foo(x, x2, x3::B, xs...) = 2
which correctly captures cases where any of the first three arguments is B:
julia> foo(B())
2
julia> foo(A(), B())
2
julia> foo(A(), A(), B())
2
But past that point, we hit the generic method and get 1.
julia> foo(A(), A(), A(), B())
1
So what are my options, other than defining up to some max number of arguments? I tried
julia> foo(x, xs::Union{Any,B}...) = 2
but this appears to be piracy, and overwrites the original f(x, xs...) method.
Maybe this isn’t possible?
As to why I want this: in BorrowChecker.jl, I wish to overload the method
Base.rand(rng::AbstractRNG, d::Integer, dims::Integer...)
for cases where at least one of (d, dims...) is type AllWrappers{<:Integer} (this AllWrappers type alias is a union of Borrowed and Owned wrapper objects). I could define all the permutations up to some integer, but seems like there should be a better way. Or maybe the answer is simply “don’t do this”… Or use Cassette.jl (now broken, sadly)… but, I think it would be nice to be able to overload methods like this.