Return multiple values: Difference between revisions
(added haskell, ocaml, sml) |
(added scheme) |
||
Line 298: | Line 298: | ||
puts "33 + 12 = #{sum}" |
puts "33 + 12 = #{sum}" |
||
puts "33 - 12 = #{difference}"</lang> |
puts "33 - 12 = #{difference}"</lang> |
||
=={{header|Scheme}}== |
|||
Scheme can return multiple values using the <code>values</code> function, which uses continuations: |
|||
<lang scheme>(define (addsub x y) |
|||
(values (+ x y) (- x y)))</lang> |
|||
You can use the multiple values using the <code>call-with-values</code> function: |
|||
<lang scheme>(call-with-values |
|||
(lambda () (addsub 33 12)) |
|||
(lambda (sum difference) |
|||
(display "33 + 12 = ") (display sum) (newline) |
|||
(display "33 - 12 = ") (display difference) (newline)))</lang> |
|||
The syntax is kinda awkward. SRFI 8 introduces a <code>receive</code> construct to make this simpler: |
|||
<lang scheme>(receive (sum difference) (addsub 33 12) |
|||
; in this scope you can use sum and difference |
|||
(display "33 + 12 = ") (display sum) (newline) |
|||
(display "33 - 12 = ") (display difference) (newline))</lang> |
|||
SRFI 11 introduces a <code>let-values</code> construct to make this simpler: |
|||
<lang scheme>(let-values (((sum difference) (addsub 33 12))) |
|||
; in this scope you can use sum and difference |
|||
(display "33 + 12 = ") (display sum) (newline) |
|||
(display "33 - 12 = ") (display difference) (newline))</lang> |
|||
=={{header|Standard ML}}== |
=={{header|Standard ML}}== |
Revision as of 06:47, 21 October 2011
Show how to return more than one value from a function.
C++
The new 2011 C++ standard includes tuples, which allow a number of different values of even different types to be passed around. <lang cpp>#include <algorithm>
- include <iostream>
- include <tr1/tuple>
std::tr1::tuple<const int , const int> minmax ( const int * numbers , const int num ) {
const int *maximum = std::max_element ( numbers , numbers + num ) ; const int *minimum = std::min_element ( numbers , numbers + num ) ; std::tr1::tuple<const int , const int> result( *maximum , *minimum ) ; return result ;
}
int main( ) {
const int numbers[ ] = { 17 , 88 , 9 , 33 , 4 , 987 , -10 , 2 } ; int numbersize = sizeof( numbers ) / sizeof ( int ) ; std::tr1::tuple<const int , const int> result = minmax( numbers , numbersize ) ; std::cout << "The greatest number is " << std::tr1::get<0>( result ) << " , the smallest " << std::tr1::get<1>( result ) << " !\n" ; return 0 ;
}</lang> Output:
The greatest number is 987 , the smallest -10 !
Common Lisp
Besides the obvious method of passing around a list, Common Lisp also allows a function to return multiple values. When citing the return values, if no interest is shown for multiple values, only the first (the primary return value) is used. Multiple values are not a data structure such as a tuple, list or array. They are a true mechanism for returning multiple values.
Returning a single value is accomplished by evaluating an expression (which itself yields a single value) at the end of a body of forms.
<lang lisp>(defun return-three ()
3)</lang>
The next possibility is that of returning no values at all. For this, the values
function is used, with no arguments:
<lang lisp>(defun return-nothing ()
(values))</lang>
To combine the values of multiple expressions into a multi-value return, values
is used with arguments. The following is from an interactive CLISP session. CLISP's listener shows multiple values separated by a semicolon:
<lang lisp>[1]> (defun add-sub (x y) (values-list (list (+ x y) (- x y)))) ADD-SUB [2]> (add-sub 4 2) ; 6 (primary) and 2 6 ; 2 [3]> (add-sub 3 1) ; 4 (primary) and 2 4 ; 2 [4]> (+ (add-sub 4 2) (add-sub 3 1)) ; 6 + 4 10 [5]> (multiple-value-call #'+ (add-sub 4 2) (add-sub 3 1)) ; 6+2+4+2 14</lang>
What happens if something tries to use the value of a form which returned (values)
? In this case the behavior defaults to taking the value nil
:
<lang lisp>(car (values)) ;; no error: same as (car nil)</lang>
What if the values
function is applied to some expressions which also yield multiple values, or which do not yield any values? The answer is that only the primary value is taken from each expression, or the value nil
for any expression which did not yield a value:
<lang lisp>(values (values 1 2 3) (values) 'a)</lang>
yields three values:
-> 1; NIL; A
This also means that values
can be used to reduce a multiple value to a single value:
<lang lisp>;; return exactly one value, no matter how many expr returns,
- nil if expr returns no values
(values expr)</lang>
Multiple values are extracted in several ways.
1. Binding to variables:
<lang lisp>(multiple-value-bind (dividend remainder) (truncate 16 3)
;; in this scope dividend is 5; remainder is 1 )</lang>
2. Conversion to a list:
<lang lisp>(multiple-value-list (truncate 16 3)) ;; yields (5 1)</lang>
3. Reification of multiple values as arguments to another function:
<lang lisp>;; pass arguments 5 1 to +, resulting in 6: (multiple-value-call #'+ (truncate 16 3))</lang>
4. Assignment to variables:
<lang lisp>;; assign 5 to dividend, 1 to remainder:
(multiple-value-setq (dividend remainder) (truncate 16 1))</lang>
(values ...)
syntax is treated as a multiple value place by setf
and other operators, allowing the above to be expressed this way:
<lang lisp>(setf (values dividend remainder) (truncate 16 1))</lang>
D
<lang d>import std.stdio, std.typecons;
auto addSub(T)(T x, T y) {
return tuple(x + y, x - y);
}
void main() {
auto r = addSub(33, 12); writefln("33 + 12 = %d\n33 - 12 = %d", r.tupleof);
}</lang> Output:
33 + 12 = 45 33 - 12 = 21
This pull request:
https://github.com/D-Programming-Language/dmd/pull/341
if accepted will allow nice tuple destructuring code like: <lang d>(auto m1, m2) = addSub(33, 12);</lang>
Factor
With stack-oriented languages like Factor, a function returns multiple values by pushing them on the data stack. For example, this word */ pushes both x*y and x/y.
<lang factor>USING: io kernel math prettyprint ; IN: script
- */ ( x y -- x*y x/y )
[ * ] [ / ] 2bi ;
15 3 */
[ "15 * 3 = " write . ] [ "15 / 3 = " write . ] bi*</lang>
Its stack effect declares that */ always returns 2 values. To return a variable number of values, a word must bundle those values into a sequence (perhaps an array or vector). For example, factors (defined in math.primes.factors and demonstrated at Prime decomposition#Factor) returns a sequence of prime factors.
Go
Functions can return multiple values in Go:
<lang go>func addsub(x, y int) (int, int) {
return x + y, x - y
}</lang>
Or equivalently using named return style:
<lang go>func addsub(x, y int) (sum, difference int) {
sum = x + y difference = x - y return
}</lang>
When a function returns multiple values, you must assign to a comma-separated list of targets:
<lang go>sum, difference := addsub(33, 12) fmt.Printf("33 + 12 = %d\n", sum) fmt.Printf("33 - 12 = %d\n", difference)</lang>
Haskell
Every function returns one value. The conventional way to return multiple values is to return a tuple.
<lang haskell>addsub x y =
(x + y, x - y)</lang>
You can use pattern matching to extract the components:
<lang haskell>main = do
let sum, difference = addsub 33 12 putStrLn $ "33 + 12 = " ++ show sum putStrLn $ "33 - 12 = " ++ show difference</lang>
Icon and Unicon
Icon and Unicon values range from simple atomic values like integers and strings to structures like lists, tables, sets, records. The contents of structures are heterogeneous and any of them could be used to return multiple values all at once. Additionally, generators are supported that return multiple results one at a time as needed.
The following examples return 1, 2, 3 in different ways:
<lang Icon>procedure retList() # returns as ordered list return [1,2,3] end
procedure retSet() # returns as un-ordered list insert(S := set(),3,1,2) return S end
procedure retLazy() # return as a generator suspend 1|2|3 end
procedure retTable() # return as a table T := table() T["A"] := 1 T["B"] := 2 T["C"] := 3 return T end
record retdata(a,b,c)
procedure retRecord() # return as a record, least general method return retdata(1,2,3) end</lang>
J
To return multiple values in J, you return an array which contains multiple values. Since the only data type in J is array, this is sort of like asking how to return only one value in another language.
<lang j> 1 2+3 4 4 6</lang>
OCaml
Every function returns one value. The conventional way to return multiple values is to return a tuple.
<lang ocaml>let addsub x y =
x + y, x - y</lang>
(Note that parentheses are not necessary for a tuple literal in OCaml.)
You can use pattern matching to extract the components:
<lang ocaml>let sum, difference = addsub 33 12 in
Printf.printf "33 + 12 = %d\n" sum; Printf.printf "33 - 12 = %d\n" difference</lang>
PARI/GP
The usual way to return multiple values is to put them in a vector: <lang parigp>foo(x)={
[x^2, x^3]
};</lang>
PHP
Every function returns one value. The conventional way to return multiple values is to bundle them into an array.
<lang php>function addsub($x, $y) {
return array($x + $y, $x - $y);
}</lang>
You can use the list()
construct to assign to multiple variables:
<lang php>list($sum, $difference) = addsub(33, 12); echo "33 + 12 = $sum\n"; echo "33 - 12 = $difference\n";</lang>
PicoLisp
A PicoLisp function returns a single value. For multiple return values, a cons pair or a list may be used. <lang PicoLisp>(de addsub (X Y)
(list (+ X Y) (- X Y)) )</lang>
Test: <lang PicoLisp>: (addsub 4 2) -> (6 2)
- (addsub 3 1)
-> (4 2)
- (+ (car (addsub 4 2)) (car (addsub 3 1)))
-> 10
- (sum + (addsub 4 2) (addsub 3 1))
-> 14</lang>
Pike
multiple values are returned through an array. an array can be assigned to separate variables. <lang Pike>array(int) addsub(int x, int y) {
return ({ x+y, x-y });
}
[int z, int w] = addsub(5,4);</lang>
Python
Every function returns one value. The conventional way to return multiple values is to bundle them into a tuple.
<lang python>def addsub(x, y):
return x + y, x - y</lang>
(Note that parentheses are not necessary for a tuple literal in Python.)
You can assign to a comma-separated list of targets:
<lang python>sum, difference = addsub(33, 12) print "33 + 12 = %s" % sum print "33 - 12 = %s" % difference</lang>
Ruby
Every function returns one value. The conventional way to return multiple values is to bundle them into an Array.
Use an array literal:
<lang ruby>def addsub(x, y)
[x + y, x - y]
end</lang>
Or use return
with 2 or more values:
<lang ruby>def addsub(x, y)
return x + y, x - y
end</lang>
(With at least 2 values, return
makes a new Array. With 1 value, return
passes the value, without making any Array. With 0 values, return
passes nil
.)
Assignment can split the Array into separate variables.
<lang ruby>sum, difference = addsub(33, 12) puts "33 + 12 = #{sum}" puts "33 - 12 = #{difference}"</lang>
Scheme
Scheme can return multiple values using the values
function, which uses continuations:
<lang scheme>(define (addsub x y)
(values (+ x y) (- x y)))</lang>
You can use the multiple values using the call-with-values
function:
<lang scheme>(call-with-values
(lambda () (addsub 33 12)) (lambda (sum difference) (display "33 + 12 = ") (display sum) (newline) (display "33 - 12 = ") (display difference) (newline)))</lang>
The syntax is kinda awkward. SRFI 8 introduces a receive
construct to make this simpler:
<lang scheme>(receive (sum difference) (addsub 33 12)
; in this scope you can use sum and difference (display "33 + 12 = ") (display sum) (newline) (display "33 - 12 = ") (display difference) (newline))</lang>
SRFI 11 introduces a let-values
construct to make this simpler:
<lang scheme>(let-values (((sum difference) (addsub 33 12)))
; in this scope you can use sum and difference (display "33 + 12 = ") (display sum) (newline) (display "33 - 12 = ") (display difference) (newline))</lang>
Standard ML
Every function returns one value. The conventional way to return multiple values is to return a tuple.
<lang sml>fun addsub (x, y) =
(x + y, x - y)</lang>
You can use pattern matching to extract the components:
<lang sml>let
val (sum, difference) = addsub (33, 12)
in
print ("33 + 12 = " ^ Int.toString sum ^ "\n"); print ("33 - 12 = " ^ Int.toString difference ^ "\n")
end</lang>
Tcl
Tcl commands all return a single value, but this value can be a compound value such as a list or dictionary. The result value of a procedure is either the value given to the return
command or the result of the final command in the body in the procedure. (Commands that return “no” value actually return the empty string.)
<lang tcl>proc addsub {x y} {
list [expr {$x+$y}] [expr {$x-$y}]
}</lang>
This can be then assigned to a single variable with set
or to multiple variables with lassign
.
<lang tcl>lassign [addsub 33 12] sum difference
puts "33 + 12 = $sum, 33 - 12 = $difference"</lang>