Next: srfi receive spec, Previous: srfi receive abstract, Up: srfi receive [Index]
Although R5RS supports multiple–valued expressions, it provides
only the essential procedures values
and call-with-values
.
It is evident that the authors expected Scheme programmers to define
other constructs in terms of these, abstracting common patterns of use.
One such pattern consists in binding an identifier to each of the values of a multiple–valued expression and then evaluating an expression in the scope of the bindings. As an instance of this pattern, consider the following excerpt from a quicksort procedure:
(call-with-values [lambda () (partition (precedes pivot) others)] [lambda (fore aft) (append (qsort fore) (cons pivot (qsort aft)))])
Here partition
is a multiple–valued procedure that takes two
arguments, a predicate and a list, and returns two lists, one comprising
the list elements that satisfy the predicate, the other those that do
not. The purpose of the expression shown is to partition the list
others, sort each of the sublists, and recombine the results into
a sorted list.
For our purposes, the important step is the binding of the identifiers
fore and aft to the values returned by partition
. Expressing the
construction and use of these bindings with the call-by-values
primitive is cumbersome: One must explicitly embed the expression that
provides the values for the bindings in a parameterless procedure, and
one must explicitly embed the expression to be evaluated in the scope of
those bindings in another procedure, writing as its parameters the
identifiers that are to be bound to the values received.
These embeddings are boilerplate, exposing the underlying binding mechanism but not revealing anything relevant to the particular program in which it occurs. So the use of a syntactic abstraction that exposes only the interesting parts (the identifiers to be bound, the multiple–valued expression that supplies the values, and the body of the receiving procedure) makes the code more concise and more readable:
(receive (fore aft) [partition (precedes pivot) others] [append (qsort fore) (cons pivot (qsort aft))])
The advantages are similar to those of a let
–expression over a
procedure call with a lambda
–expression as its operator. In
both cases, cleanly separating a “header” in which the bindings are
established from a “body” in which they are used makes it easier to
follow the code.
Next: srfi receive spec, Previous: srfi receive abstract, Up: srfi receive [Index]