status: final (2005-08-12)
keywords: Binding, Multiple-Value Returns
See also SRFI 8: receive: Binding to multiple values, SRFI 11: Syntax for receiving multiple values, and SRFI 210: Procedures and Syntax for Multiple Values.library name: let
This SRFI is a proposal for extending
      let, let*, and letrec for
      receiving multiple values. The syntactic extension is fully compatible
      with the existing syntax. It is the intention that single-value bindings,
      i.e. (let ((var expr)) ...), and multiple-value binding can
      be mixed freely and conveniently.
      
The most simple form of the new syntax is best explained by an example:
(define (quo-rem x y)
  (values (quotient x y) (remainder x y)))
(define (quo x y)
  (let ((q r (quo-rem x y)))
    q))
      The procedure quo-rem delivers two
      values to its continuation. These values are received as q
      and r in the let-expression of the procedure
      quo. In other words, the syntax of let is
      extended such that several variables can be specified---and these
      variables receive the values delivered by the expression (quo-rem x
      y).
      
The syntax of let is further
      extended to cases in which a rest argument receives the list of all
      residual values. Again by example,
      
(let (((values y1 y2 . y3+) (foo x))) body)In this example,
values is a
syntactic keyword indicating the presence of multiple values to be received,
and y1, y2, and y3+, resp., are
variables bound to the first value, the second value, and the list of the
remaining values, resp., as produced by (foo x). The syntactic
keyword values allows receiving all values as in (let
(((values . xs) (foo x))) body). It also allows receiving no values at
all as in (let (((values) (for-each foo list))) body).A common application of binding multiple values
      is decomposing data structures into their components. This mechanism is
      illustrated in its most primitive form as follows: The procedure
      uncons (defined below) decomposes a pair x into
      its car and its cdr and delivers them as two values to its continuation.
      Then an extended let can receive these values:
      
(let ((car-x cdr-x (uncons x))) (foo car-x cdr-x))
Of course, for pairs this method is probably
      neither faster nor clearer than using the procedures car and
      cdr. However, for data structures doing substantial work
      upon decomposition this is different: Extracting the element of highest
      priority from a priority queue, while at the same time constructing the
      residual queue, can both be more efficient and more convenient than doing
      both operations independently. In fact, the quo-rem example
      illustrates this point already as both quotient and remainder are
      probably computed by a common exact division algorithm. (And often
      caching is used to avoid executing this algorithm twice as often as
      needed.)
      
As the last feature of this SRFI, a mechanism
      is specified to store multiple values in heap-allocated data structures.
      For this purpose, values->list and
      values->vector construct a list (a vector, resp.) storing
      all values delivered by evaluating their argument expression. Note that
      these operations cannot be procedures.