<p><em>(inspired by <a href="https://languagedesign.stackexchange.com/q/611">this question</a>)</em></p>
<p>Different programming languages handle multiple return values differently, used in functions such as <code>divmod</code>.</p>
<p>For example, in Python or Haskell, you would just return a tuple. In Go or Lua, you would return multiple values - not a specific type.</p>
<p>What are the different ways of handling multiple return values, and what are the pros and cons of each?</p>

<language-comparison><tuple>
What are the different ways of handling multiple return values?
<h1>Redirections</h1>
<p>Good insights could be found in pipe redirections in a shell script.</p>
<pre><code>{ { tee &gt;(xxd &gt;&amp;3) &gt;(wc -c &gt;&amp;4) | ...; } 3&gt;&amp;1 | ...; } 4&gt;&amp;1 | ...
</code></pre>
<p>Unfortunately, if we want to read the values in the same command, it either needs some dirty hacks, or needs named variables or named pipes, in which case it might be better to just use normal named variables. But we get the idea.</p>

CC BY-SA 4.0
2023-07-07T04:30:44.027Z
2023-07-07T04:30:44.027Z
user23013
<h1>Push them onto the stack</h1>
<p>This really only applies to stack-based languages, and perhaps Assembly. The good thing about this approach is that its somewhat more natural to work with the returned values. If you do divmod, you can pop once to get the quotient, pop the next element to get the remainder. The downside is that if you want to call a function that returns multiple values and immediately pass them on, it might be a bit cumbersome, depending on the language.</p>

CC BY-SA 4.0
2023-05-19T01:58:27.540Z
2023-05-19T01:58:27.540Z
user
CC BY-SA 4.0
2023-05-26T03:06:20.640Z
Worth noting that this is Lua's solution too,  despite not being a stack-based language.
ATaco
<h1>Structured Bindings</h1>
<p>A lot of languages have a feature where you can unpack the return value of a function into multiple individual variables. For instance, it looks like this in C++:</p>
<pre><code>auto [q, r] = divmod(26,7);
</code></pre>
<p><code>divmod</code> in this case would return a value similar to some of the other answers (such as a custom object or builtin tuple type). The nice thing about structured bindings is that they provide a nice syntax for something that is generally tedious. For instance, if <code>divmod</code> here returned a pair of values, then the code above is really syntactic sugar for the following:</p>
<pre><code>auto ret = divmod(26,7);
auto q = ret.first;
auto r = ret.second;
</code></pre>

CC BY-SA 4.0
2023-05-19T02:53:41.577Z
2023-05-19T02:53:41.577Z
Isaiah
<h2>Custom types</h2>
<p>In languages such as Java and Kotlin, which really love their nominal typing, you would make a new class specific to that one function. For example, <code>divmod</code> might return a <code>DivmodResult</code> object with fields <code>quotient</code> and <code>remainder</code> (Kotlin does have a <code>Pair</code> class in its standard library, but it's dropped actual tuples now).</p>
<p>Advantages:</p>
<ul>
<li>When you have to return 4 or more values, it really helps to have a class specifically for that purpose if you have a statically typed language. I'd rather see a return type of <code>FooResult</code> than some enormous tuple like <code>(int, String, BarProducer, String, int)</code></li>
</ul>
<p>Disadvantages:</p>
<ul>
<li>Making a whole class for a single function is annoying. Some languages do have syntactic sugar for this (e.g. <code>data class</code> in Kotlin) but it's so much easier to use something like tuples or lists instead. In Java, you'll have to make getters and setters and constructors for a minor class that might only be used in one or two places.</li>
</ul>

CC BY-SA 4.0
2023-05-19T01:50:11.490Z
2023-05-19T01:50:11.490Z
user
CC BY-SA 4.0
2023-05-19T02:03:35.653Z
Note that Pair and Triple exist in Kotlin’s stdlib, and in 3rd party Java libraries
Seggan
CC BY-SA 4.0
2023-05-19T02:04:28.780Z
@Seggan Yes, but that's only for 2/3 values, and Java code conventions encourage making your own classes afaik
user
CC BY-SA 4.0
2023-05-19T02:13:55.317Z
Beyond 3 values is where you’d want to make a user defined class anyway
Seggan
<h1>Generators</h1>
<p>Some modern languages like Python and JavaScript provide generator functions, which return an object that yields all return values in succession (an iterator object). It has much simpler usage than defining an object/custom type. A JavaScript example would be as follows:</p>
<pre><code>const foo = function*() {
  yield 'a';
  yield 'b';
  yield 'c';
};
</code></pre>
<p>These are useful as they can be directly used in loops or just collected into an array for future use.</p>

CC BY-SA 4.0
2023-05-19T02:50:59.250Z
2023-05-19T02:50:59.250Z
Razetime
CC BY-SA 4.0
2023-07-06T13:07:24.157Z
I think generators are not used to return multiple return values but rather return multiple times where each iteration can be computed as needed. When you want to return multiple things in Python or JavaScript you can just return a tuple/array. Using generators instead of tuples is just making things more complicated for no good reason.
Aiono
CC BY-SA 4.0
2023-08-23T18:27:55.960Z
Generators is a very valid option when the "multiple return values" are array/list-like.
Pablo H
<h1>Pointer Parameters</h1>
<p>Languages that have pointers or references accept, as parameters, pointers to output variables. Example:</p>
<pre><code>void sincos(float t, float *s, float *c) {
    *s = sin(t);
    *c = cos(t);
}
</code></pre>
<p>The main advantage is that this is flexible and simple to implement in languages such as C, but handling be slower than handling a return value directly.</p>

CC BY-SA 4.0
2023-05-19T01:57:00.510Z
2023-05-19T01:57:00.510Z
CPlus
CC BY-SA 4.0
2023-05-19T02:00:41.590Z
It may also be somewhat less safe, since you don't have a guarantee that the pointer was actually set to something other than garbage/NULL.
user
CC BY-SA 4.0
2023-05-19T03:26:06.683Z
More generally, these are referred to as "[output parameters](https://en.wikipedia.org/wiki/Parameter_(computer_programming)#Output_parameters)" or "out-parameters". It's possible for a language to support them with syntax like `void sincos(float t, out float s, out float c)` without the language necessarily supporting pointers.
kaya3
<h2>Common Lisp</h2>
<p>You can return zero, one or more values, using <a href="http://clhs.lisp.se/Body/f_values.htm" rel="noreferrer"><code>VALUES</code></a>:</p>
<pre><code>(values 1 2 3)
</code></pre>
<p>For example you can also return <em>no value</em> with:</p>
<pre><code>(values)
</code></pre>
<p>The first value is the primary return value, and without capturing the secondary values explicitly, this is the only one that is used by other expressions:</p>
<pre><code>(* (values 1 5 7) 2)
== (* 1 2)
== 2
</code></pre>
<p>An expression can explicitly ask for multiple values:</p>
<pre><code>(multiple-value-bind (q r) (floor 13 2)
  (format t &quot;13 is ~d * 2 + ~d&quot; q r))
</code></pre>
<p>The above prints:</p>
<pre><code>13 is 6 * 2 + 1
</code></pre>
<p>You can bind less variables than there are values:</p>
<pre><code>(multiple-value-bind (q) (floor 13 2) ...)
</code></pre>
<p>Or more:</p>
<pre><code>(multiple-value-bind (q r s) (floor 13 2) ...)
</code></pre>
<p>In which case <code>s</code> will be <code>nil</code>.</p>
<p>The multiple value mechanism is constrained by <a href="http://www.lispworks.com/documentation/HyperSpec/Body/v_multip.htm" rel="noreferrer"><code>MULTIPLE-VALUES-LIMIT</code></a> which is allowed to be as low as 20.</p>
<p>In my current SBCL environment, this value is larger:</p>
<pre><code>USER&gt; multiple-values-limit
4611686018427387903
</code></pre>
<h3>Implementation</h3>
<p>Multiple values as defined here are interesting because it offers a different way to pass data than using objects or lists. It behaves like optional function parameters but for return values: the caller does not need to unpack values to get the primary value, so you can transparently pass additional return values without breaking existing code (like you can add optional parameters without breaking existing code).</p>
<p>Also, you can grab all the values as a list, using <a href="http://clhs.lisp.se/Body/m_mult_1.htm" rel="noreferrer"><code>MULTIPLE-VALUE-LIST</code></a>, and convert a list to multiple values with <a href="http://clhs.lisp.se/Body/f_vals_l.htm#values-list" rel="noreferrer"><code>VALUES-LIST</code></a>, like you can bind function arguments  with <code>&amp;rest</code> and use them with <code>apply</code>.</p>
<p>In that regard values are dual to function arguments.</p>
<p>Multiple values were defined to allow better compilation mechanisms that just relying on existing sequences: maybe a smart-enough compiler can pass a temporary list through registers, but having a dedicated mechanism for it makes it easier to implement.</p>
<p>In a Lisp that compiles code, like SBCL for x86, multiple values use registers, flags and possible stack space: the first three return values are in edx/edi/esi registers, the remaining on the stack (rbp), the carry flag (stc/clc) indicates if there <em>are</em> multiple values, and ecx stores how many return values there are (this is a guess based on the disassembly output).</p>
<p>For example:</p>
<pre><code>USER&gt; (disassemble (lambda () (values 10 20)))
; disassembly for (LAMBDA ())
; Size: 40 bytes. Origin: #x54EF67FC                          ; (LAMBDA ())
; 7FC:       498B4510         MOV RAX, [R13+16]               ; thread.binding-stack-pointer
; 800:       488945F8         MOV [RBP-8], RAX
; 804:       BA14000000       MOV EDX, 20
; 809:       BF28000000       MOV EDI, 40
; 80E:       488D5D10         LEA RBX, [RBP+16]
; 812:       B904000000       MOV ECX, 4
; 817:       BE17010050       MOV ESI, #x50000117             ; NIL
; 81C:       F9               STC
; 81D:       488BE5           MOV RSP, RBP
; 820:       5D               POP RBP
; 821:       C3               RET
; 822:       CC10             INT3 16                         ; Invalid argument count trap
NIL
</code></pre>
<p>Above, <code>20</code> and <code>40</code> are respectively the representation of 10 and 20, because there is a shift of one binary digit to the left due to values being tagged.</p>
<p>The primary value 10 is stored in <code>edx</code>, the second one in <code>edi</code>. With more parameters for <code>values</code> they are stored relatively to <code>rpb</code>:</p>
<pre><code>; 84:       BA14000000       MOV EDX, 20
; 89:       BF28000000       MOV EDI, 40
; 8E:       BE3C000000       MOV ESI, 60
; 93:       48C745F050000000 MOV QWORD PTR [RBP-16], 80
; 9B:       48C745E864000000 MOV QWORD PTR [RBP-24], 100
; A3:       48C745E078000000 MOV QWORD PTR [RBP-32], 120
</code></pre>
<p>Most functions however only use a single return value, for which it only needs to store the return value in <code>edx</code> and clear the carry flag (<code>clc</code>):</p>
<pre><code>USER&gt; (disassemble (lambda () 10))
; disassembly for (LAMBDA ())
; Size: 21 bytes. Origin: #x54EE17BC                          ; (LAMBDA ())
; BC:       498B4510         MOV RAX, [R13+16]                ; thread.binding-stack-pointer
; C0:       488945F8         MOV [RBP-8], RAX
; C4:       BA14000000       MOV EDX, 20
; C9:       488BE5           MOV RSP, RBP
; CC:       F8               CLC
; CD:       5D               POP RBP
; CE:       C3               RET
; CF:       CC10             INT3 16                          ; Invalid argument count trap
NIL
</code></pre>
<h3>Disadvantages</h3>
<p>A drawback of this representation of multiple values for me is that they are positional, and you have to take care of which secondary value is more important than another otherwise you keep having to bind values you don't care. Here for example, <code>get-decoded-time</code> returns 9 values: second, minute, hour, date, month, year, day of week, daylight-saving flag and timezone.</p>
<p>If I don't care about seconds, I have to ignore it (otherwise there is a warning about an unused variable):</p>
<pre><code>(multiple-value-bind (s m h) (get-decoded-time)
  (declare (ignore s))
  (format t &quot;~a:~a&quot; h m))
</code></pre>
<p>I said above that values mirror function calls, but function calls also accepts <code>&amp;key</code> parameters, which are named parameters, but there is no equivalent for values. The below code, for example, doesn't work:</p>
<pre><code>(multiple-value-bind (&amp;key hour minute) (get-decoded-time)
  (format t &quot;~a:~a&quot; hour minute))
</code></pre>
<p>Another problem is that its a bit verbose, but some things are like that in Common Lisp, that's not a problem of the approach by itself which could be adapted to have a shorter syntax.</p>
<p>Also, knowing that you only expect N values from the caller could be used to avoid computing the remaining M-N values (M&gt;N) in the called function, in particular if you only ever need the primary return value you could avoid computing them in the called function: this is not possible here I guess because you can have side-effects when computing secondary values (but often, secondary values are bonus values you had to compute anyway).</p>

CC BY-SA 4.0
2023-07-06T14:39:10.683Z
2023-07-06T14:53:44.403Z
2023-07-06T14:53:44.403Z
coredump
# What are the different ways of handling multiple return values?
Posted by: username_0 on 2023-05-19
*(inspired by [this question](https://languagedesign.stackexchange.com/q/611))*

Different programming languages handle multiple return values differently, used in functions such as `divmod`.

For example, in Python or Haskell, you would just return a tuple. In Go or Lua, you would return multiple values - not a specific type.

What are the different ways of handling multiple return values, and what are the pros and cons of each?
**Tags:** language-comparison tuple
---
## 7 answers
### Answer by username_2 on 2023-05-19. Score: 12
# Push them onto the stack

This really only applies to stack-based languages, and perhaps Assembly. The good thing about this approach is that its somewhat more natural to work with the returned values. If you do divmod, you can pop once to get the quotient, pop the next element to get the remainder. The downside is that if you want to call a function that returns multiple values and immediately pass them on, it might be a bit cumbersome, depending on the language.
> **Comments:**
> **username_3** (2023-05-26): Worth noting that this is Lua's solution too,  despite not being a stack-based language.  
---
### Answer by username_4 on 2023-05-19. Score: 11
Structured Bindings
A lot of languages have a feature where you can unpack the return value of a function into multiple individual variables. For instance, it looks like this in C++:
auto [q, r] = divmod(26,7);

divmod in this case would return a value similar to some of the other answers (such as a custom object or builtin tuple type). The nice thing about structured bindings is that they provide a nice syntax for something that is generally tedious. For instance, if divmod here returned a pair of values, then the code above is really syntactic sugar for the following:
auto ret = divmod(26,7);
auto q = ret.first;
auto r = ret.second;
---
### Answer by username_2 on 2023-05-19. Score: 11
## Custom types

In languages such as Java and Kotlin, which really love their nominal typing, you would make a new class specific to that one function. For example, `divmod` might return a `DivmodResult` object with fields `quotient` and `remainder` (Kotlin does have a `Pair` class in its standard library, but it's dropped actual tuples now).

Advantages:

* When you have to return 4 or more values, it really helps to have a class specifically for that purpose if you have a statically typed language. I'd rather see a return type of `FooResult` than some enormous tuple like `(int, String, BarProducer, String, int)`

Disadvantages:

* Making a whole class for a single function is annoying. Some languages do have syntactic sugar for this (e.g. `data class` in Kotlin) but it's so much easier to use something like tuples or lists instead. In Java, you'll have to make getters and setters and constructors for a minor class that might only be used in one or two places.
> **Comments:**
> **username_5** (2023-05-19): Note that Pair and Triple exist in Kotlin’s stdlib, and in 3rd party Java libraries  
> **username_2** (2023-05-19): @Seggan Yes, but that's only for 2/3 values, and Java code conventions encourage making your own classes afaik  
> **username_5** (2023-05-19): Beyond 3 values is where you’d want to make a user defined class anyway  
---
### Answer by username_6 on 2023-05-19. Score: 6
Generators
Some modern languages like Python and JavaScript provide generator functions, which return an object that yields all return values in succession (an iterator object). It has much simpler usage than defining an object/custom type. A JavaScript example would be as follows:
const foo = function*() {
  yield 'a';
  yield 'b';
  yield 'c';
};

These are useful as they can be directly used in loops or just collected into an array for future use.
> **Comments:**
> **username_7** (2023-07-06): I think generators are not used to return multiple return values but rather return multiple times where each iteration can be computed as needed. When you want to return multiple things in Python or JavaScript you can just return a tuple/array. Using generators instead of tuples is just making things more complicated for no good reason.  
> **username_8** (2023-08-23): Generators is a very valid option when the "multiple return values" are array/list-like.  
---
### Answer by username_9 on 2023-05-19. Score: 6
Pointer Parameters
Languages that have pointers or references accept, as parameters, pointers to output variables. Example:
void sincos(float t, float *s, float *c) {
    *s = sin(t);
    *c = cos(t);
}

The main advantage is that this is flexible and simple to implement in languages such as C, but handling be slower than handling a return value directly.
> **Comments:**
> **username_2** (2023-05-19): It may also be somewhat less safe, since you don't have a guarantee that the pointer was actually set to something other than garbage/NULL.  
> **username_10** (2023-05-19): More generally, these are referred to as "[output parameters](https://en.wikipedia.org/wiki/Parameter_(computer_programming)#Output_parameters)" or "out-parameters". It's possible for a language to support them with syntax like `void sincos(float t, out float s, out float c)` without the language necessarily supporting pointers.  
---
### Answer by username_11 on 2023-07-06. Score: 5
Common Lisp
You can return zero, one or more values, using VALUES:
(values 1 2 3)

For example you can also return no value with:
(values)

The first value is the primary return value, and without capturing the secondary values explicitly, this is the only one that is used by other expressions:
(* (values 1 5 7) 2)
== (* 1 2)
== 2

An expression can explicitly ask for multiple values:
(multiple-value-bind (q r) (floor 13 2)
  (format t "13 is ~d * 2 + ~d" q r))

The above prints:
13 is 6 * 2 + 1

You can bind less variables than there are values:
(multiple-value-bind (q) (floor 13 2) ...)

Or more:
(multiple-value-bind (q r s) (floor 13 2) ...)

In which case s will be nil.
The multiple value mechanism is constrained by MULTIPLE-VALUES-LIMIT which is allowed to be as low as 20.
In my current SBCL environment, this value is larger:
USER> multiple-values-limit
4611686018427387903

Implementation
Multiple values as defined here are interesting because it offers a different way to pass data than using objects or lists. It behaves like optional function parameters but for return values: the caller does not need to unpack values to get the primary value, so you can transparently pass additional return values without breaking existing code (like you can add optional parameters without breaking existing code).
Also, you can grab all the values as a list, using MULTIPLE-VALUE-LIST, and convert a list to multiple values with VALUES-LIST, like you can bind function arguments  with &rest and use them with apply.
In that regard values are dual to function arguments.
Multiple values were defined to allow better compilation mechanisms that just relying on existing sequences: maybe a smart-enough compiler can pass a temporary list through registers, but having a dedicated mechanism for it makes it easier to implement.
In a Lisp that compiles code, like SBCL for x86, multiple values use registers, flags and possible stack space: the first three return values are in edx/edi/esi registers, the remaining on the stack (rbp), the carry flag (stc/clc) indicates if there are multiple values, and ecx stores how many return values there are (this is a guess based on the disassembly output).
For example:
USER> (disassemble (lambda () (values 10 20)))
; disassembly for (LAMBDA ())
; Size: 40 bytes. Origin: #x54EF67FC                          ; (LAMBDA ())
; 7FC:       498B4510         MOV RAX, [R13+16]               ; thread.binding-stack-pointer
; 800:       488945F8         MOV [RBP-8], RAX
; 804:       BA14000000       MOV EDX, 20
; 809:       BF28000000       MOV EDI, 40
; 80E:       488D5D10         LEA RBX, [RBP+16]
; 812:       B904000000       MOV ECX, 4
; 817:       BE17010050       MOV ESI, #x50000117             ; NIL
; 81C:       F9               STC
; 81D:       488BE5           MOV RSP, RBP
; 820:       5D               POP RBP
; 821:       C3               RET
; 822:       CC10             INT3 16                         ; Invalid argument count trap
NIL

Above, 20 and 40 are respectively the representation of 10 and 20, because there is a shift of one binary digit to the left due to values being tagged.
The primary value 10 is stored in edx, the second one in edi. With more parameters for values they are stored relatively to rpb:
; 84:       BA14000000       MOV EDX, 20
; 89:       BF28000000       MOV EDI, 40
; 8E:       BE3C000000       MOV ESI, 60
; 93:       48C745F050000000 MOV QWORD PTR [RBP-16], 80
; 9B:       48C745E864000000 MOV QWORD PTR [RBP-24], 100
; A3:       48C745E078000000 MOV QWORD PTR [RBP-32], 120

Most functions however only use a single return value, for which it only needs to store the return value in edx and clear the carry flag (clc):
USER> (disassemble (lambda () 10))
; disassembly for (LAMBDA ())
; Size: 21 bytes. Origin: #x54EE17BC                          ; (LAMBDA ())
; BC:       498B4510         MOV RAX, [R13+16]                ; thread.binding-stack-pointer
; C0:       488945F8         MOV [RBP-8], RAX
; C4:       BA14000000       MOV EDX, 20
; C9:       488BE5           MOV RSP, RBP
; CC:       F8               CLC
; CD:       5D               POP RBP
; CE:       C3               RET
; CF:       CC10             INT3 16                          ; Invalid argument count trap
NIL

Disadvantages
A drawback of this representation of multiple values for me is that they are positional, and you have to take care of which secondary value is more important than another otherwise you keep having to bind values you don't care. Here for example, get-decoded-time returns 9 values: second, minute, hour, date, month, year, day of week, daylight-saving flag and timezone.
If I don't care about seconds, I have to ignore it (otherwise there is a warning about an unused variable):
(multiple-value-bind (s m h) (get-decoded-time)
  (declare (ignore s))
  (format t "~a:~a" h m))

I said above that values mirror function calls, but function calls also accepts &key parameters, which are named parameters, but there is no equivalent for values. The below code, for example, doesn't work:
(multiple-value-bind (&key hour minute) (get-decoded-time)
  (format t "~a:~a" hour minute))

Another problem is that its a bit verbose, but some things are like that in Common Lisp, that's not a problem of the approach by itself which could be adapted to have a shorter syntax.
Also, knowing that you only expect N values from the caller could be used to avoid computing the remaining M-N values (M>N) in the called function, in particular if you only ever need the primary return value you could avoid computing them in the called function: this is not possible here I guess because you can have side-effects when computing secondary values (but often, secondary values are bonus values you had to compute anyway).
---
### Answer by username_1 on 2023-07-07. Score: 1
Redirections
Good insights could be found in pipe redirections in a shell script.
{ { tee >(xxd >&3) >(wc -c >&4) | ...; } 3>&1 | ...; } 4>&1 | ...

Unfortunately, if we want to read the values in the same command, it either needs some dirty hacks, or needs named variables or named pipes, in which case it might be better to just use normal named variables. But we get the idea.
---
