best to show the example.
I see how to refactor it and work with two functions, multidispatchly. My use case is a preference for write-once algorithmics … and experimented seeking a flexible, easy-peasy union of Vector, SVector, NTuple where all constituents of these containers share type.
Is there a nice approach to this?
const VecOrNTuple{T,N} = Union{Vector{T}, NTuple{N,T}}
function fn(x::VecOrNTuple{T,N}) where {T,N}
if isdefined(localcontext, :N) # ymmv
T, N
else
N
end
end
First of all, if I were you I would seriously consider abandoning the idea of using NTuple
and simply using AbstractVector
instead. An SVector
is basically an NTuple
anyway, so, if you want your NTuple
to behave like a Vector
, why not just use SVector
? Of course, I don’t know the context of what you’re doing, so perhaps I’m missing something.
That said, if you really feel you need to do this, multiple dispatch is still your friend, you shouldn’t feel like you need to circumvent it somehow. You can always define a helper function thus:
g(x::Vector{T}) where {T} = T
g(x::NTuple{N,T}) where {N,T} = (T, N)
function fn(x::VectorOrNTuple{T,N}) where {T,N}
τ = g(x) # this is just an ordinary tuple
# here you can write arbitrarily complicated code using τ
end
And you can of course write as many functions as you want that use g
. Note that there may be performance limitations if you start accessing the components of \tau
with getindex
since the compiler may not know the type of the resulting objects. I would be interested to know of constant propagation solves those, so it might be something fun to test on 0.7 or 1.0.
1 Like
good points – thank you for the writing and confirming something for others.
1 Like