f(x){T, N} where N may not exist

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