values - return multiple values

LIBRARY

(import (rnrs))                     ;R6RS
(import (rnrs base))                ;R6RS
(import (scheme r5rs))              ;R7RS
(import (scheme base))              ;R7RS

SYNOPSIS

(values obj ...)

DESCRIPTION

Delivers all of its arguments to its continuation. The values procedure might be defined as follows:

(define (values . things)
  (call-with-current-continuation
    (lambda (cont) (apply cont things))))

The continuations of all non-final expressions within a sequence of expressions, such as in lambda, begin, let, let*, letrec, letrec*, let-values, let*-values, case, and cond forms, usually take an arbitrary number of values (but see the note on compatibility). Except for these and the continuations created by call-with-values, let-values, and let*-values, and define-values, continuations implicitly accepting a single value, such as the continuations of operator and operands of procedure calls or the test expressions in conditionals, take exactly one value. The effect of passing an inappropriate number of values to such a continuation is undefined.

This feature implements true multiple return values. On the language level it works more in the way that Golang does it and less like how tuples or lists are used to simulate this feature in languages like Python and JavaScript.

IMPLEMENTATION NOTES

Implementations vary greatly in how they treat multiple values that are returned to single-value continuations. Portable programs should not rely on any of these behaviors.
Chez Scheme
Single-value continuations verify that they receive a single value and otherwise raise an exception.

Note however that the source optimizer utilizes the underspecification of what happens when multiple values are returned to single-value continuations. An example is that (let ((x (values 1 2))) x) is optimized to (values 1 2).

Chibi Scheme
Multiple values are represented as a list where the car is (values).
GNU Guile
Single-value continuations that receive multiple values use the first value. Single-value continuations that receive zero values raise an exception.
Ikarus Scheme
Single-value continuations verify that they receive a single value and otherwise raise an exception.
IronScheme
Single-value continuations that receive zero or multiple values receive an object that represents those values.
Larceny Scheme
Single-value continuations that receive multiple values use the first value. Single-value continuations that receive zero values receive the unspecified value.
Loko Scheme
Single-value continuations that receive multiple values use the first value. Single-value continuations that receive zero values receive a void value.
Racket
Single-value continuations verify that they receive a single value and otherwise raise an exception.
Sagittarius
Single-value continuations that receive multiple values use the first value. Single-value continuations that receive zero values receive the unspecified value.
Vicare Scheme
A type checker verifies that the right number of values are returned. In particular, it raises a &syntax error if two branches if an if return different numbers of values.

RETURN VALUES

Returns the values given as arguments.

EXAMPLES

(let-values (((a b) (values 1 2))
             ((c d) (values 3 4)))
  (list a b c d))
=> (1 2 3 4)

(define (quotient+remainder n d)
  (let ((q (quotient n d)))
    (values q (- n (* q d)))))
(quotient+remainder 10 3)
=> 3
=> 1

((lambda (x) x) (values 1 2)) => unspecified

APPLICATION USAGE

This procedure is often combined with syntax to receive the values, such as let-values(3scm). Another option is receive from SRFI-8, which only binds a single set of values.

RATIONALE

R6RS Rationale
Many computations conceptually return several results. Scheme expressions implementing such computations can return the results as several values using the values procedure. Of course, such expressions could alternatively return the results as a single compound value, such as a list, vector, or a record. However, values in programs usually represent conceptual wholes; in many cases, multiple results yielded by a computation lack this coherence. Moreover, this would be inefficient in many implementations, and a compiler would need to perform significant optimization to remove the boxing and unboxing inherent in packaging multiple results into a single values. Most importantly, the mechanism for multiple values in Scheme establishes a standard policy for returning several results from an expression, which makes constructing interfaces and using them easier.

[It then goes on to discuss the contentious issue of what should happen when the wrong number of values is passed to a continuation.]

COMPATIBILITY

This procedure is compatible across all Schemes that support it as long as the continuation accepts the given number of values.

R5RS contains the following language, which is not in R6RS and R7RS:

Except for continuations created by the call-with-values procedure, all continuations take exactly one value.

ERRORS

This procedure can raise exceptions with the following condition types:
&assertion (R6RS)
The wrong number of values was passed to a continuation set up with call-with-values.
R7RS
Returning the wrong number of values to a continuation not created by call-with-values, and which is not the non-final expression of a sequence, is unspecified and implementation-dependent.

SEE ALSO

apply(3scm), let-values(3scm), call-with-values(3scm)

STANDARDS

R5RS, R6RS, R7RS

HISTORY

First appeared in R5RS. The R4RS formal semantics notes:

The reason that expression continuations take sequences of values instead of single values is to simplify the formal treatment of procedure calls and to make it easy to add multiple return values.

AUTHORS

This page is part of the scheme-manpages project. It includes materials from the RnRS documents. More information can be found at https://github.com/schemedoc/manpages/.


Markup created by unroff 1.0sc,    March 04, 2023.