[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