[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

How about dropping semi-variable-arity?



Sebastian Egner wrote:

> At the point I decide to drop rest-list values the SRFI will be
> withdrawn, I promise.  The whole point of this SRFI is to integrate
> multiple values in all their beauty smoothly into the Scheme
> language.

I can imagine you sometimes might not know how many values something
will produce, and thus it's important to be able to receive an
arbitrary number of values in a list.

However, if that is provided, are you wedded to the idea that lambda's
feature of semi-variable-arity argument lists like (a b . c) must also
be supported?

If you're thinking you want that so that you can use a destructuring
idiom like:

  (let* ((foo '(1 2 3 4 5))
	 ((values x y . z) (unlist foo)))
    (list x y (apply + z)))
  => (1 2 12)

I would like to point out that that requires Z to be bound to a list
of three new pairs and *not* to the cddr of FOO, so this really isn't
an appropriate idiom for the typical operation of extracting the first
few elements of a list and the remainder.  As has been suggested, the
appropriate construct for that would be a pattern-match facility.

If you drop support for semi-variable-arity, and you drop support for
zero-value clauses (which I will discuss more below) then you can dump
the VALUES keyword entirely, because (values . x) clauses can be more
simply and clearly written -- without the triple-open-paren -- using
values->list:

  (let (((values . x) (foo)))
    <body>)

becomes

  (let ((x (values->list (foo))))
    <body>)

With respect to zero-valued clauses: I'm not sure it really makes
sense to allow "binding clauses" that do not actually create any
bindings.  In what situations are you thinking these would be useful?
The only kind of LET in which I can imagine them being used is a LET*
into which you want to insert some expression for effect.  Would that
perhaps be better expressed with BEGIN?  That is, a sequence of LET*
binding clauses like this:

  ((values) (foo))
  (x y (bar))

could instead be written:

  (x y (begin (foo) (bar))

At least, it would be equivalent if the specification of BEGIN were a
little different than it is.  If your goal is to update the basic
syntaxes, like LET, to be more multiple-values aware, then it might
make sense to also specify two begins: STRICT-BEGIN and LOOSE-BEGIN.
STRICT-BEGIN is the one you would use in the above example.  It would
require all the expressions but the last to return zero values.
LOOSE-BEGIN would allow the non-terminal expressions to return any
number of values.  The name of LOOSE-BEGIN should perhaps be just
BEGIN.  I understand the r5rs authors came very close to deciding to
specify BEGIN as having the semantics of LOOSE-BEGIN, but the change
did not make it into the final draft.

-al