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)

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. What’s 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. Let’s 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)

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)

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 valuesValues 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 that’s all you need to know to work with multiple values!

  1. Since we are using floor from the repl, all of the values are shown.

8 thoughts on “Multiple-value-bind

  1. I find that use of multiple-value-bind tends to quickly get your code indented far to the right. Many people have tried to address this issue by inventing mother-of-all macros that generalize let* into accepting arbitrary binders. Marco Baringer once taught me to instead use a generic nest macro that reuses existing binders without causing runaway indentation, by automatically nesting all expressions. It’s now part of uiop and fare-utils.

  2. Multiple values definitely aren’t unique. Scheme has them exactly like Common Lisp, except that what happens when the caller isn’t set up to receive the number of values that the callee returns. Some Schemes use the Common Lisp rules (truncate to one value or supply a value out of nowhere), some throw an error, some silently misbehave (leading to a later error): details here. This gives implementers more choices while requiring users to be more careful.

    In Python, ML, and Haskell, multiple values are a first-class construct called tuples, which can be thought of in Lisp terms as immutable lists or structs without field names.

    In Ada, Algol 68, and C#, the convention is to label certain parameters to a function as output parameters; the actual arguments passed must be places in the sense of setf. Assignment to the output parameters within a function causes the places to be side-effected. Internally this is typically implemented using boxed references.

    1. Almost all of the kinds of multiple values you mention increase coupling between the caller and callee. If you suddenly decide that you want the callee to return an additional value, you have to change all of the callers to ignore it. Although, I do like how Guile and NexJ signal an error when returning zero values to a function that expects some.

  3. True. That’s where the tuple system is a win, but it is heavier-weight because it is first-class. The output-parameter system also works with coupling, provided the language has static or dynamic overloading on arity. Googling shows that Go has Scheme-style multiple values; Lua has CL-style multiple values; Octave has output parameters; Ruby returns multiple values as an array.

    Fare: Scheme now has let-values and let*-values, as well as define-values (which inherently conses, unless it is primitive).

    1. You are right about the output-parameter system in a language which supports optional arguments provides the same functionality. I’m just trying to understand how tuples are a win. If you have a function that returns a single value and want to change it to one that returns a tuple, doesn’t all of the code that expects a single value have to be changed to expect a tuple?

  4. I don’t think any discussion of multiple-values, perhaps even an introductory one, is complete without at least mentioning MULTIPLE-VALUE-CALL. It is the primitive and is truly mind-expanding. MULTIPLE-VALUE-BIND is (at least conceptually) defined in terms of it, as is MULTIPLE-VALUE-LIST.

    As for using VALUES with a single argument to force the returning of only the primary value among multiple values, while it’s what has been used traditionally I prefer to use IDENTITY as that makes the code even more clear because IDENTITY always accepts and returns only a single argument (so unlike VALUES you don’t have to check how many arguments are given). If you see (identity foo) you can immediately assume that the code wants to evaluate FOO and then return only the primary value (or NIL if no values).

  5. In most languages, a 1-tuple is the same as a single value. In Python, this is not so, and x = f() where f now returns multiple values will cause x to have a tuple value.

    Scheme does not support the full strength of multiple-value-call, because there can only be one sender of values rather than an arbitrary number as CL allows. On the good side, call-with-values is a procedure rather than a macro. The first argument is a thunk which is invoked, and then all its results are passed to the second argument, which is a procedure that can accept that many arguments. It’s trivial to write a two-argument version of the multiple-value-call macro on top of this.

  6. I understand that a benefit of multiple values is they don’t cons in efficient implementations, the values being present in CPU registers for the caller to use or ignore. They certainly come in handy for communicating metadata that is not always wanted or expected, such as an error caught and suppressed by IGNORE-ERRORS.

Leave a Reply

Your email address will not be published. Required fields are marked *