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

Proposal #13: Structure Sharing in Arguments



Received: from SCRC-QUABBIN.ARPA by SAIL.STANFORD.EDU with TCP; 28 Jul 86  12:15:21 PDT
Received: from FIREBIRD.SCRC.Symbolics.COM by QUABBIN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 24557; Mon 28-Jul-86 09:31:04 EDT
Date: Mon, 28 Jul 86 09:31 EDT
From: David C. Plummer <DCP@QUABBIN.SCRC.Symbolics.COM>
Subject: Proposal #13: Structure Sharing in Arguments
To: Scott E. Fahlman <Fahlman@C.CS.CMU.EDU>, common-lisp@SU-AI.ARPA
In-Reply-To: <FAHLMAN.12226167028.BABYL@C.CS.CMU.EDU>
Message-ID: <860728093136.8.DCP@FIREBIRD.SCRC.Symbolics.COM>

    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))