[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
From: Steve Bacher (CSDL)
Subject: What's all this fuss about &rest destruction?
Having been watching while just about everyone on the CL mailing list
has argued about the &REST proposal, I have to jump in and make a point.
Many of you are now contending that there is no difference between
restricting the user from destroying a list passed as an argument to a
function and restricting the user from passing same list back as a
return value or storing it in "stable" storage (e.g. SETQ'ing some
global variable thereto). I find it incredible that this idea should
be suddenly gaining concurrency.
Ever since LISP began (I realize this is a meaningless argument to most
Common LISPers)... or maybe I should say that scattered throughout
every LISP manual and certainly CLtL (though I can't quote any exact
references), it has been emphasized that the destructive operations
are DANGEROUS and should be used WITH CAUTION only by EXPERIENCED
LISP PROGRAMMERS. It follows that if you are about to do something
that will destructively update a list, you'd better be damned sure
that nobody else is pointing to that list. The only way to be certain
of this is (usually) if you create the list yourself out of fresh
conses (or if you get the list back from a function which you know has
created a list safe for destruction).
Conversely, I find it hard to accept the notion that Common LISP may
specify that some particular kind of argument to a function is
GUARANTEED to be freshly consed and therefore destructible. Suppose you
have a function like
(defun foo (a b &rest c) ...)
Why should I be guaranteed that the value bound to c will be
clobberable, when I am not given such a guarantee for a and b?
Perhaps your answer will be that functions should always do COPY-LIST on
any list arguments they pass to other functions, since those other
functions might wish to do NCONC or RPLACA on their args? :-)
On the other hand, NEVER in the history of any LISP that I know has
there been a rule that for some situation or other, the user may not
pass a given object back as a return value or store it somewhere
permanent. Such a restriction is truly abhorrent and contrary to the
spirit of the language. But it sure might make some compiler
implementors happy. Imagine: the whole problem of upward funargs
could have been avoided so easily - just tell users that functions
may be passed as arguments, but they may not be returned as values or
assigned to global variables! We might never had had to design all
those hairy mechanisms for saving environments in heap storage.
If the rationale behind this is that certain implementations
put their &REST args on the stack to save some conses, that's just too
bad. (Should we support implementations that keep lexical closure
environments on the stack because it's just too hard to let users
pass lexical closures around as arguments?) I agree with
Scott Fahlman's suggestion for an additional mechanism in the
language to provide for LEXPR'ish passing of varying numbers of args
on the stack as an alternative to consing &REST lists.
In short, there most definitely IS a qualitative distinction between
proscribing wanton clobbering of lists regardless of their origin
and limiting users' right to do with arguments what they please in
- Steve Bacher