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.