[R6RS] multiple-value binding
dyb at cs.indiana.edu
dyb at cs.indiana.edu
Wed Feb 15 11:25:02 EST 2006
I'd like to revive the multiple-value binding discussion. I believe
there have been three basic proposals for a multiple-value binding form,
which I've identified as 1, 2, and 3 below. To that I'm adding a fourth.
1. (let-values ([idspec expr] ...) body)
idspec -> id | (id ...) | (id id ... . id)
- with idspec -> id, id is bound to list of all expr values
- fully general: can accept n or 'n or more' values with this syntax
for any n >= 0
- adds new syntactic form to the language
2. (let ([id ... expr] ...) body)
- there is no way to accept 'n or more' values with this syntax, for any n
- formatting is problematic with id ... plus expr don't fit on one line
- may cause confusion for novices when no syntax error is reported for
something like (let ([x y e]) ---)
3. (let ([idspec expr] ...) body)
idspec -> id | (id ...) | (id id ... . id)
- with idspec -> id, id is bound to expr's single return value
- there is no way to accept 'zero or more' values with this syntax
4. (let ([idspec expr] ...) body)
idspec -> id | vidspec
vidspec -> (values . id) | (values id ...) | (values id id ... . id)
- with idspec -> id, id is bound to expr's single return value
- fully general: can accept n or 'n or more' values with this syntax
for any n >= 0
My take:
- I prefer 1 > 4 > 3 > 2. I prefer 1 and 4 over 2 and 3 because 1 and
4 are more general and make the intended meaning more clear.
I prefer 1 over 4 because I don't like gumming up the syntax of let.
I prefer 3 over 2 because it's more general, formats better, and is
less likely to lead to confusion.
- Although I prefer 1 to 4, I included 4 in case others are also unhappy
with 2 and 3 yet prefer extending the syntax of let to adding a
separate form.
- Whichever option we choose, I think we should include a let* variant
as well.
- I'm less sure about letrec or letrec* variants. It's straightforward
to write allocation- and assignment-free transformations for both let
and let* variants into 'single value' let (and call-with-values),
but I do not believe it's possible to write an allocation- and
assignment-free transformation for a letrec or letrec* variant into
'single-value' letrec. This will lead to greater implementation
complexity or to poorer error checking and/or less efficiency.
I don't think that the need for multiple-value letrec and letrec* is
all that strong in any case, although I have wished for define-values
on occasion.
Incidentally, a more radical proposal is to flush the 'dot' notation
in favor of &rest (or just &). Then it becomes straightforward to
generalize option 3:
3g. (let ([idspec expr] ...) body)
idspec -> id | (id ...) | (id ... & id)
If we were to go this route, I'd want to replace . with & in the syntaxes
of lambda and define as well, and eliminate (lambda x body) in favor of
(lambda (& x) body).
Kent
More information about the R6RS
mailing list