# Generated function with multiple return values

How can I create a generated function, that returns two arguments, see the following example:

``````ex = [:(x+y), :(x-y)]
@generated function f(x,y)
ex
end
f(2,3) # returns 5
``````

That works fine. And how about returning two arguments (similar to the following code)?

``````@generated function f(x,y)
ex,ex
end
``````

The generator (the body of the generated function) must always return exactly one expression. That is to say, it must return exactly the entire body of the function you want to generate. That’s why your second example fails: you’re returning two expressions, not a single expression.

What you need to do instead is to think about what the function you’re trying to generate would look like. It would probably look something like this:

``````julia> function f_generated(x, y)
((x + y), (x - y))
end
``````

Your generator needs to return the body of that function, or, in other words, it needs to return:

``````julia> :((x + y), (x - y))
``````

Now you need to figure out how to construct `:((x + y), (x - y))` out of your two expressions in `ex`. You can do that by splicing each expression into a new tuple expression:

``````julia> :(\$(ex), \$(ex))
:((x + y, x - y))
``````

So that’s exactly what your generator should return:

``````julia> @generated function f(x, y)
:(\$(ex), \$(ex))
end
f (generic function with 1 method)

julia> f(1, 2)
(3, -1)
``````
4 Likes

Thanks for the thourough and clear answer! One small further question as I do not manage to get that working with expressions:
How would the return code line `:(\$(ex), \$(ex))` look like assuming the array `ex` has many entries and I want to use something like the splatting syntax?

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
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), \$(ex))
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)
``````
3 Likes