Common Lisp is a pretty unique language. One of the many features that makes Common Lisp such an awesome language is multiple values. Yes, you read right. In Common Lisp it is possible for a function to return more than a single value. One example of a function that takes advantage of multiple values is floor. Floor takes a number as its argument and returns two values, whatever was passed in rounded down and the remainder.
(floor 3.5) => 3 0.5
When you use floor in the manner above, you get two values back, 3 as the first return value, and 0.5 as the second. Whats really cool is that the values besides the first are completely ignored unless you explicitly ask for them.1 This means you can pretend that floor returns only a single value as long as you don’t need the other ones. Notice how in the following example, the + function is not aware of the second value returned by floor:
(+ (floor 3.5) 10) => 13
Now you may be wondering, How can I obtain other values besides the first one?. Well, there are several macros for doing that, the main one being multiple-value-bind. To use multiple-value-bind, you specify a list of the variables you want to bind each value to, followed by the expression that will return multiple values. Lets say you want to multiply the two values returned by floor together. Here is how you would do that with multiple-value-bind:
(multiple-value-bind (val remainder) (floor 3.5) (* val remainder)) => 1.5
It is also easy to create your own function that returns multiple values. All you need to do is pass each value you want to return to the values function. Below is a function which returns both twice its argument and three times its argument:
(defun multiples (x) (values (* 2 x) (* 3 x))) (multiples 10) => 20 30
There is just one more thing you need to know about multiple values. If the last call of a function is to another that returns multiple values, the first function will return all of the values the second one returns. If you were to write a function that doubles its argument and then uses floor to round it down, that function will return both values that are returned by floor.
(defun double-and-round-down (x) (floor (* 2 x))) (double-and-round-down 5.25) => 10 0.5
This behavior may or may not be desired. The standard way to make sure your function only returns a single value is to wrap the function that returns multiple values with a call to values. Values will pay attention only to the first value and will return just that and nothing else.
(defun double-and-round-down (x) (values (floor (* 2 x)))) (double-and-round-down 5.25) => 10
And thats all you need to know to work with multiple values!
- Since we are using floor from the repl, all of the values are shown.