[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Proposal #13: Structure Sharing in Arguments
Date: Sun, 27 Jul 1986 23:01 EDT
From: "Scott E. Fahlman" <Fahlman@C.CS.CMU.EDU>
The first part of this seems to have generated no controversy. The
second part, about &REST arguments, has generated a lot of controversy,
in part because it is stated in a way that seems to presuppose that it
is OK to destructively modify most lists.
We seem to be in agreement that &REST args must be true lists, and must
not evaporate when passed upwards
or stored in stable storage
; this should be made explicit since it
is an occasional source of confusion, as it was in the discussion of
this issue. (The issue here is not whether implementations currently
comply with this, or even whether they plan to comply with in the
future; the issue is what the language spec requires.)
We also seem to agree that a good rule is that a list should not ever be
destructively modifed unless the programmer understands where it came
from and who else might be holding onto it.
The remaining contentious issue is whether users may assume that the
&REST list in a function is a freshly-consed list, or whether the &REST
list may incorporate the list (or part of it) passed as the last
argument to APPLY.
(Speaking for myself, I initially favored the fresh-consed option as
being cleaner, but Weinreb has convinced me that the APPLY optimization
is important for some kinds of code. I now believe that we should not
outlaw this optimization just so that people can smash &REST args
without thinking about the consequences. We're weighing a real source
of efficiency against the freedom to do something that most programmers
will rarely want to do, and in those cases they can copy to be safe.)
It is important that programmers not avoid the &REST feature because
they believe it is universally expensive in time and storage.
Clarifications:
13A: Specify that the &REST or &BODY argument to a macro may be the very
list from the macro call, and not a copy. Therefore, if this argument
is destructively modified, the originl text of the macro may also be
altered.
13B: Specify explicitly that the &REST argument in a function has
indefinite extent and may, for example, be returned to the function's
caller.
13C: The &REST list in a function is not necessarily a freshly-consed
list. If the function is called with APPLY, the &REST list may share
top-level structure with the last argument to the APPLY. Users should
keep this in mind if they are considering destructive modifications to
such a list.
- OR -
13C': The &REST list in a function is freshly consed upon function entry.
It shares no top-level structure with any pre-existing list.
My opinion still stands: it depends on how hard you look. I still think
13B and 13C are in conflict:
(defun copy-list (list)
(apply #'list list))
(defun list (&rest list)
list)
I think 13C' implies global inefficiency and may detract programmers
from using &REST.
I think the necessary >>semantics<< are 13B and 13C', and that a
compiler that can prove the &REST list is being in only downward ways
(all destructive modification should be considered "upward") is allowed
to keep the list "consed on the stack" in the implementations that work
that way, or "shared with last arg to APPLY" in the implementatins that
work that way as well/instead. &KEY is essentially a standard deconding
of an &REST arg, and &KEY is completely downward and never (unless
accompanied by an explicit &REST) needs to freshly cons the implicit
&REST arg.
We may want to decide on the name of a
declaration to override the case when the compiler can't figure it out.
(defun 3arg-format (stream string args)
(apply #'format stream string args))
(defun send-it (string &rest args)
(declare (sys:downward-&rest-arg))
(3arg-format t string args))