Lisp: Returning Multiple Values From A Function

Written by on January 6, 2016 in LISP, Programming with 0 Comments

One of the interesting features of Lisp is its support for returning multiple values from a function, without bundling the values in a special container. Languages such as Python and Ruby support multi-value return (although there are subtle differences from Lisp). In C++11, we can use std::make_tuple() and std::tie().

To take an example, in Lisp, the built-in function floor returns both the quotient and reminder. However, the caller may use only the first value (quotient) and ignore the second value:

(setf quotient (floor 7 3))

Here the call to floor looks exactly like a call to a regular function that returns a single value, and as expected, the variable quotient gets the value 2 (the reminder is discarded).

Let us first see how a function can return multiple values. The following function computes both the sum and difference of two numbers passed as arguments:

(defun sum-diff (num1 num2)

(values (+ num1 num2) (- num1 num2)))

The values function bundles all its arguments (which are evaluated) into a value list to be used by the caller. It is important to keep in mind that returning multiple values is not the same as returning a list of many values. The former is more efficient and flexible.

OK. How do we consume multiple values from a function? We use the multiple-value-bind construct.

(multiple-value-bind (s d) (sum-diff)

(format t “Sum = ~D, Difference = ~D~%” s d))

multiple-value-bind is a macro, whose first argument is a list of variables, the second argument is a multi-valued expression, and the rest are forms that are evaluated in the context of the variable bindings.

Going back to the floor example, we can use it thus:

(multiple-value-bind (quot rem) (floor 7 3)

(format t “Quotient = ~D, Reminder = ~D~%” quot rem))

if there are more variables than values returned by the multi-valued function, the extra variables get nil. If there are fewer variables than returned values, then only the corresponding values are bound.

When do we write such multi-valued functions? There are two scenarios:

* The values computed are logically related. In the case of floor, the quotient and reminder are logically related

* It is more efficient to compute the values together because most of the steps are common

(Please note that the sum-diff function falls into neither of the two scenarios, and hence is not a good example of a multi-valued function.)

As an interesting use of the values function, the following swaps the state of the two variables a and b:

(setf (values a b) (values b a))

Tags: ,

Subscribe

If you enjoyed this article, subscribe now to receive more just like it.

Subscribe via RSS Feed

Leave a Reply

Your email address will not be published.

Top