I find that cases like this are easier to handle by constructing the expression directly. You can construct any Julia expression by directly building an Expr()
, and you can find out how a particular expression is built using dump()
. For example:
julia> dump(:(a, b))
Expr
head: Symbol tuple
args: Array{Any}((2,))
1: Symbol a
2: Symbol b
We can infer from that dump()
output that we can construct a tuple expression like so:
julia> Expr(:tuple, :a, :b)
:((a, b))
Or to construct a tuple expression from arbitrarily many other expressions, we can do:
julia> Expr(:tuple, ex...)
:((x + y, x - y))
By the way, I should mention that you actually don’t need a @generated
function in the case you posted originally. A @generated
function is necessary when you want the generated code to depend on the types of the input arguments, but your code doesn’t actually depend on the types of x
or y
.
Instead, you can just use @eval
to construct the function right away:
julia> @eval function f(x, y)
($(ex[1]), $(ex[2]))
end
f (generic function with 1 method)
julia> f(1, 2)
(3, -1)
or, using the splatting syntax:
julia> @eval function f(x, y)
$(Expr(:tuple, ex...))
end
f (generic function with 1 method)
julia> f(1, 2)
(3, -1)