[racket] multiple-value sugar in "let"* forms
Eli Barzilay wrote at 06/03/2012 11:25 PM:
> The way I see it, there are several problems with internal `define's
> as they currently stand, in decreasing order of importance:
>
> 1. Easy to make hard-to-find bugs in both code refactoring and in new
> code.
>
I think that a lot of these problems would be avoided if in most cases
we could get rid of toplevel-like magic for internal bindings, and also
have the internal "define" form have syntactic terms to make its scope
explicit (and control flow can just proceed into "SCOPE-BODY" from the
context in which the "define/scope" appears):
(define/scope ID VAL-EXPR SCOPE-BODY ...+)
Since each such binding form in a series, even when such bindings don't
depend on each other, would increase rightward drift, since they'd have
to be nested, the form should accommodate multiple simultaneous bindings
(simultaneous wrt both "VAL-EXPR"s and bindings):
(define/scope ((ID VAL-EXPR) ...+) SCOPE-BODY ...+)
For non-simultaneous bindings, in which a "VAL-EXPR" can refer to a
previously-encountered "ID", we can avoid the rightward drift of nesting
by introducing an additional form:
(define/scope/sequenced ((ID VAL-EXPR) ...+) SCOPE-BODY ...+)
For the occasions on which we want to bind mutually-recursive internal
procedures simultaneously, with some magic approaching that of toplevel,
we should warn of that fact with an identifier we don't like to type as
much:
(define/scope/here-there-be-dragons ((ID VAL-EXPR) ...+) SCOPE-BODY ...+)
For recursive algorithms, someone suggested that it would be very
convenient if "SCOPE-BODY" could treat the binding context as a
procedure, providing different values for the "ID"s, so we get an
additional form:
(define/scope/proc PROC-ID ((ID VAL-INIT) ...+) SCOPE-BODY ...+)
Now we just need shorter names for these different forms.
> 2. Lack of ability to mimic the `let*'-with-repeated-name idiom.
>
> 3. Reduces the "verbosity" when measured in nestings, but tends to add
> more text overall; in addition, the indentation of the named
> expression is usually the same because `define' is so long; and in
> addition, it's common to type many definitions, and as much as I
> use a sophisticated editor I end up typing it verbatim a lot.
>
The internal "define" verbosity increases more in syntax transformer
templates.
> Where the gaps are substantial (that is, #1 is much more important IMO
> than #2, which is much more important than #3).
>
> Such a `def+' (which is subtly different from the previously mentioned
> `define*') is something that I'm not sure that the definition-context-
> police will let through, but having #2 seems still important enough
> that I worry that it won't become popular and therefore the #1 point
> is still pending.
>
I can see why some people want to have internal "define": it looks
friendlier, you can toss in a binding in many places without having to
think too much about scope or nest your parens, and you don't have to
tell newbies that they need different syntax for internal bindings (even
though the semantics might be more different than they assume).
I'm also wary of the pitfall of inflexibly clinging to the familiar.
I've been using "let" in Scheme descendants for a decade, and in other
Lisp descendants for a decade before that, so I'm very comfortable with
"let"*. The relative advantages of "define" would have to be big for me
to choose to give up the relative advantages of "let"* to which I've
become accustomed. I don't actually know how you'd improve "define" to
make it more compelling to me.
I asked about multiple-value "let"*. All I wanted was to renovate my
kitchen, but instead you're trying to sell me a downtown penthouse.
You're going to have to sell me on why I'd want the downtown lifestyle,
and allay my concerns about social diseases. We could just renovate my
kitchen *while* you refine the downtown living story.
Neil V.