[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Multiple values in Dylan
- To: moon@cambridge.apple.com (David A. Moon)
- Subject: Re: Multiple values in Dylan
- From: meehan@src.dec.com
- Date: Mon, 26 Oct 92 14:49:16 -0800
- Cc: info-dylan@cambridge.apple.com
- In-reply-to: Message of Mon, 26 Oct 92 13:46:59 EDT from moon@cambridge.apple.com (David A. Moon) <9210261846.AA05377@cambridge.apple.com>
From: moon@cambridge.apple.com (David A. Moon)
Date: Mon, 26 Oct 92 13:46:59 EDT
... I think it's incumbent on anyone proposing significant language
changes to give examples of how common usages would change under
the proposal ...
OK. My basic point was that we could make the language simpler,
more elegant, and compiler-friendlier by cleaning up multiple values.
Specifics:
1. Ditch the part of BIND that allows extra values and fills in missing
values with #f. Allow BIND to take #key and #next. Specify that
VALUES must produce exactly the number and types of values that BIND
is prepared to receive; VALUES and BIND must agree, just as APPLY
and METHOD do. Then there's only one protocol in the language for
passing arguments.
2. For the cases where you want to ignore extra values, we would
add a macro or special form, e.g., (VAL1 expression), that takes
an expression that produces at least one value, and returns the first
value. Something with this sort of effect (but done more efficiently):
(define-macro val1 (expression)
(bind ((vals (gensym)))
`(bind ((#rest ,vals ,expression))
(first ,vals))))
Then you can write (* y (val1 (ceiling/ x y))), and you don't need
to add "floor1", "ceiling1", "init-value1", etc.
3. I don't think that VALUES would need to be a special form. The
compiler could be at least as smart about VALUES as it is about APPLY,
which isn't a special form, either. If, as the book suggests,
DEFINE-GENERIC-FUNCTION had a standard option for specifying the
number and types of return-values, the compiler could do a really
good job of checking for errors, avoiding the allocation of #REST-sequences,
etc.
Comment: Careful readers of the manual may have noticed that the
only built-in functions that return multiple values, besides VALUES
itself, are INIT-VALUE, FLOOR, FLOOR/, CEILING, CEILING/, ROUND,
ROUND/, TRUNCATE, and TRUNCATE/ (did I miss any?), so they might
argue that this is a lot of fuss over an obscure feature of the language.
But I've found them to be quite useful; they make the language more
"functional", and they are certainly to be preferred over passing
"VAR OUT" parameters. I've seen a lot of bad Lisp code where people
cheated by adding extra return-values to encode obscure state-information,
often not even documenting them in the "white pages", so that "normal
users" would think there was only one value; this led to errors.
Cleaning up multiple values would prevent that sort of problem.
I've also programmed in languages where, in order to get the effect
of multiple values, you defined a record-type that held exactly the
right number and types of slots. This is clean and works well, but
it requires more verbose code, and it can waste storage allocation:
in the typical case, the values are extracted from the record, immediately
upon return, and bound to other variables. Multiple values could
simplify this usage as well.
--Jim