I have found that using ntuple in generated functions produces better code (faster, and with fewer allocations), than constructing the tuple expression manually. Presumably the code that ntuple generates is more inferable. From a maintenance perspective it feels preferable to use it too.
However, I can only use ntuple on the compile time constants. I have been unable to get it work with variables. To show you what I mean, the following code throws an error:
@generated function myfunc1(x::T, ::Val{N}) where {T, N}
ex = Expr(:tuple, [:(x * $i) for i in 1:N]...)
return :(SVector{N, T}($ex))
end
@generated function myfunc2(x::T, ::Val{N}) where {T, N}
ex = ntuple(i -> :(x * $i), N)
return :(SVector{N, T}($ex))
end
display(myfunc1(2., Val(3)))
display(myfunc2(2., Val(3)))
Output:
3-element SVector{3, Float64} with indices SOneTo(3):
2.0
4.0
6.0
ERROR: MethodError: Cannotconvertan object of type Expr to an object of type Float64
How can I fix myfunc2 to work like myfun1?