Next: Basic Syntax Extensions Up: PLT MzScheme: Language Manual Previous: Notation

# Multiple Return Values

Most Scheme expressions return a single value. For example, in the following procedure:

      (define quotient-and-remainder
        (lambda (n d)
          (let ([q (quotient n d)]
                [r (remainder n d)])
            (cons q r))))

the expressions `(quotient n d)` and `(remainder n d)` each return a single value. The expression `(cons q r)` also returns a single value; although two other values can be extracted from the cons-cell created by `cons`, the cons-cell is itself just a single value. Thus, this `quotient-and-remainder` procedure returns a single value.

On the other hand, a context using `quotient-and-remainder` is probably interested only in the two numbers returned by the procedure, not the cons-cell used to store the numbers. A client context might be best expressed with the `let-values` form:

      (let-values ([(q r) (quotient-and-remainder-values n d)])
        (printf "~a * ~a + ~a = ~a~n" q d r n))

This `let-values` form expresses the idea that `quotient-and-remainder-values` returns two values, and these two values are bound directly to `q` and `r`. For the `let-values` expression to be correct, the `quotient-and-remainder-values` procedure must specifically return two values by using the `values` procedure:

      (define quotient-and-remainder-values
        (lambda (n d)
          (values (quotient n d)
                  (remainder n d))))

Any MzScheme expression can return multiple values. Multiple return values are generated by the `values` procedure, which bundles and returns its arguments as multiple return values. A bundle of return values is not itself a first-class value. Rather, the individual values must unbundled by the context of the expression returning multiple values. A run-time error is signaled when multiple values are returned to a context expecting a single value. For example, the following expression signals a run-time error:

       (let ([x (values 1 2)]) x)

In this example, the expression for `x`'s value must return a single value (since `x` is a single variable), but `(values 1 2)` returns multiple values to the binding context. Most contexts are like this one, expecting a single value. The `let-values` form creates a context expecting (a particular number of) multiple values. The `call-with-values` procedure also creates a multiple values return context by transforming the individual values of a multiple-value return into the arguments of a procedure call.

Binding form contexts for multiple-value expressions are discussed in section 3.5. Only the `values` and `call-with-values` procedures are described here:

- `(values v )` returns the vs as multiple values. If zero vs or more than one v is provided, the result of this expression must be used in a multiple-value context; e.g., the result must be used by `call-with-values`, `define-values`, or `let-values`, or it must be ignored. `(values v)` is always equivalent to v.
- `(call-with-values producer-proc consumer-proc)` invokes producer-proc and passes the result to consumer-proc. The producer-proc argument is a procedure that takes no arguments and returns some number of values. The consumer-proc argument is a procedure that takes the same number of arguments as the number of values returned by producer-proc. The result of the `call-with-values` expression is the result of applying consumer-proc.

Multiple return values are legal whenever the return value of an expression is ignored, or when it passed on as the result of an enclosing expression (provided that the enclosing expression can legally return multiple values). For example, either branch of an `if` expression can return multiple values; in this case the result of the entire `if` expression might be multiple values. However, the test expression of an `if` expression must return a single value because that value is used as a test. Similarly, the body expressions of a `let` form can return multiple values, but the binding expressions must return single values. (This is true even when the variable that is bound is not used in the body of the `let` expression.) An expression used in a procedure application (either as the procedure to be applied or one of the arguments) must always return a single value.

If a built-in procedure takes a procedure argument, and it does not inspect the result of the supplied procedure, then the supplied procedure can return multiple values. For example, the procedure supplied to `for-each` can return any number of values, but the procedure supplied to `map` must return a single value.

When the number of values returned by an expression does not match the number of values expected by the expression's context, the `exn:application:arity` exception is raised (at run time).

Examples: ``

      (- (values 1)) ; => -1
      (- (values 1 2)) ; => exn:application:arity, returned 2 values to single-value context
      (- (values)) ; => exn:application:arity, returned 0 values to single-value context
      (call-with-values
        (lambda () (values 1 2))
        (lambda (x y) y)) ; => 2
      (call-with-values
        (lambda () (values 1 2))
        (lambda z z)) ; => (1 2)
      (call-with-values
        (lambda () (let/cc k (k 3 4)))
        (lambda (x y) y)) ; => 4
      (call-with-values
        (lambda () (values 'hello 1 2 3 4))
        (lambda (s . l)
          (format "~s = ~s" s l))) ; => "hello = (1 2 3 4)"

Next: Basic Syntax Extensions Up: PLT MzScheme: Language Manual Previous: Notation