[racket] multiple-value sugar in "let"* forms

From: Neil Van Dyke (neil at neilvandyke.org)
Date: Sun Jun 3 14:40:36 EDT 2012

What do people think about this syntax addition for multiple values in 
"let" and "let*" (and perhaps "letrec")?

I like using multiple-value returns, but two problems with using them 
with the "let"* family:

1. "let-values" and "let*-values" are long identifiers, and increase 
rightward drift, sometimes making the difference between a line break 
needed before right-hand-side (RHS) or not (which line break is ugly in 
a "let"* form).

2. If I have an existing "let"* that's not a *"-values" that already has 
a few clauses in it, and I want to add a multiple-value LHS to it, I 
have to go to the trouble of converting it to a "-values", which 
requires editing each clause to add parentheses.

So, I've been wondering what would be a good way to support multiple 
values on a per-clause basis.  Options I see:

1. Change "(ID VAL-EXPR)" to "(ID ...+ VAL-EXPR)".  I am shying away 
from this one because it seems error-prone, and the standard indenter 
won't know a good way to break such a clause across multiple lines, but 
it does have some appeal.

2. In addition to "(ID VAL-EXPR)", have "((ID ...+) VAL-EXPR)".  This 
could work.  One drawback I see is if in the future someone wants to 
have some funky generalized-"set!" selectors that have a parenthesized 
form, and have those work with the "let"* forms.  I'm not currently 
interested in such "set!" selectors.  Another small drawback is that 
we'll sometimes see "(let (((ID" three parentheses sometimes, like we do 
with "let-values", which is not the most visually pleasant thing to see.

3. In addition to "(ID VAL-EXPR)", have "((values ID ...+) VAL-EXPR)".  
This avoids the hypothetical problem with some future "set!" selectors, 
since I doubt is going to use "values" for the name of such a selector 
with any other purpose.  This still has the three-parentheses problem 
like option #2.

4. In addition to "(ID VAL-EXPR)", have "(values ID ...+ VAL-EXPR)" or 
"(values (ID ...+) VAL-EXPR)".  This avoids the three-parens of #2 and 
#3, it's not ambiguous with "values" used as a variable name, but it 
doesn't seem very Scheme-y, it has similar indent problem to option #1, 
and we still have rightward drift because of the "values" keyword.

I lean a little towards option #2, but I think #1 or #3 would still be 
an improvement.  #4 seems less-Schemely syntax, so I am reluctant to go 
there.

For each option, the transform to Racket's canonical "let-values" is  
trivial.

I don't know whether there are implications for TR syntax.

A separate question -- which I don't care about, but someone else might 
-- is whether there should be ``rest'' ID in the LHS that gets a list of 
any remaining values from the RHS.  I think this came up in a SRFI 
discussion a long time ago.  I almost never have occasion to use such a 
feature, and it could complicate the syntax and the Racket compiler, so 
I'm not interested in a ``rest'' in the LHS.

Neil V.


Posted on the users mailing list.