[R6RS] summary of decisions regarding multiple values
William D Clinger
will at ccs.neu.edu
Fri Jun 23 15:56:31 EDT 2006
> In my experience, returning an unexpected number of values is a common
> programming error.
My experience is different from yours. We don't all make
the same kind of mistakes. While trying to change the
language to prevent X from making the kind of mistakes
X often makes, we shouldn't make changes that prevent Y
from employing the programming style that Y and many
other programmers have been using reliably for years.
> Furthermore, it's inconsistent to require that an expected number of
> values be passed to a procedure but not require the procedure to return an
> expected number of values.
The tenuous symmetry between calls and returns was broken
when we decided to require continuations created by begin
to accept any number of arguments. For consistency with
that decision, and for consistency with many of Scheme's
traditional equivalences, such as the equivalence between
(begin E1 E2)
((lambda (ignored) E2) E1)
our earlier decision implies that continuations created
for argument evaluation must also accept any number of
arguments. To escape that conclusion, we must either
break the traditional equivalence, or we must reconsider
our earlier decision. There is no other alternative.
> ....Based on my
> experience, doing so just masks likely program errors, and requiring the
> implementation to raise an exception is the only reasonable way to address
> this problem.
The fact remains that your experience and conclusion are
at odds with standard practice in other languages and
with some implementations of Scheme. To insist that your
preferred solution is the only reasonable way is to say
that I and all others who disagree with you are being
> On the other hand, it's easy for programmers to say explicitly when they
> don't want the additional return values, using the following wrapper from
> Ashley and Dybvig's 1994 LFP paper:
Many programmers want to ignore extra return values as a
matter of course. Using an explicit wrapper for every
procedure call they write is not a reasonable solution.
> Some of those implementors probably won't even bother to implement a safe
> mode at all, so a requirement to raise an exception won't affect them.
My most recent message to the SRFI 77 discussion list
ended with this paragraph:
Legalistic attempts to require some precise quality
of implementation often inspire an equally legalistic
search for loopholes, with consequences opposite to
A word to the wise is unnecessary.
> This discussion has nothing to do with expressions and the ways in which
> they can be composed. (car (values 3 4)) remains syntactically
> well-formed, just as is (cons 3). The discussion boils down to whether
> the former raises a run-time exception. We both agree that the latter
Composibility of expressions is not just a matter of
syntax. The multiple values of the R5RS are widely
disliked because they do not compose well with the
rest of the language. You cannot return multiple
values from any procedure that might be called in a
command context, in an argument context, or in any
other context except for the context hidden away
within the definition of call-with-values.
There have been two consistent ways to look at this.
One is that multiple values are truly a wart on the
language, and it is necessary to protect the rest of
the language from multiple values by forbidding their
use in any syntactic context that a Scheme programmer
can write. (The beauty of call-with-values is that
it hides some magical syntactic context that cannot
be written in portable Scheme.)
The other consistent way to look at this is that
multiple values are too useful to be restricted to
magical contexts, and that the proper way to deal
with them is to relax that restriction. Several
implementations have done this, and it has indeed
proved to be useful, just as in Common Lisp.
The R5RS allowed both viewpoints by saying it is an
error, but not "signals an error", for multiple
values to be returned to a continuation that wasn't
created by call-with-values. In the R5RS, "is an
error" means implementations are free to extend the
semantics to cover the error case. Thus all of the
implementations that have done so are R5RS-conforming
in this respect.
For those of us who consider multiple values too
useful to suffer arbitrary restrictions, the proposed
relaxation that allows them to be returned to command
contexts is a good one. That blesses an extension
several implementations have made.
The R6RS editors may not want to bless the extensions
that several implementations have made to allow any
number of values to be returned to argument contexts,
but it would be an entirely different thing for the
R6RS editors to *forbid* that extension. That would
destroy the uneasy truce that has developed between
the two camps.
As safety sub-editor, it is my responsibility to warn
the editors of dangerous munitions. This particular
issue is highly explosive.
> Not exactly. The traditional CPS form of (lambda () (f (g))) is
> (lambda (k) (g (lambda (v) (f v k)))).
The proper translation of that CPS-transform into
Scheme is (lambda (k) (g (lambda v (apply f k v)))).
> Any compiler that handles call-with-values and values will have to
> generalize their CPS and A-normal forms and optimizations on those forms
> anyway, so handling the (other) single-value return cases properly should
> present no additional problems.
As the author of a compiler that uses A-normal form
while handling call-with-values and values correctly,
I can report that implementing your preferred semantics
would be a mess.
> Some of the same implementors who refuse to implement return-value
> checking (and full continuations and tail recursion) might also refuse to
> implement these because it's too inefficient to compute and return both
> values and too much trouble to detect when only one value is needed.
You sound as though you don't expect very many systems
implementors to conform to the R6RS anyway. If you're
right about that, then we have even more reason not to
drive away the few who are willing.
More information about the R6RS