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: Cannotconvert
an object of type Expr to an object of type Float64
How can I fix myfunc2
to work like myfun1
?