How to use @ntuple with N derived from parameters

Below is a MWE of an error I get using @ntuple:

using StaticArrays
import Base.Cartesian: @ntuple

function times2(v::SVector{N, T}) where {N, T}
    return SVector{N, T}(@ntuple N i->v[i]*2)
end

a = randn(SVector{3, Float64})
b = times2(a)

Does anyone know what I need to change to get this code to run? I’ve tried several things already, but always get the same error:

ERROR: LoadError: MethodError: no method matching var"@ntuple"(::LineNumberNode, ::Module, ::Symbol, ::Expr)

Closest candidates are:
  var"@ntuple"(::LineNumberNode, ::Module, ::Int64, ::Any)
   @ Base cartesian.jl:199

@ntuple only works when N is a literal number, not a variable. Instead write

function times2(v::SVector{N, T}) where {N, T}
    return SVector{N, T}(ntuple(i->v[i]*2, N))
end
1 Like

I see. Is there a reason why it cannot work with a compile-time constant such as the N in my code? Or is it something that could be fixed?

Macros operate just on parsed syntax, they don’t know about compile time constants.

1 Like

Makes sense.

Unfortunately this kills performance. However, the following works well:

function times2(v::SVector{N, T}) where {N, T}
    return SVector{N, T}(ntuple(i->v[i]*2, Val(N)))
end