1
0
Fork 0
cl-sites/HyperSpec-7-0/HyperSpec/Issues/iss142_w.htm

309 lines
21 KiB
HTML
Raw Normal View History

2024-04-01 10:24:07 +02:00
<!-- Common Lisp HyperSpec (TM), version 7.0 generated by Kent M. Pitman on Mon, 11-Apr-2005 2:31am EDT -->
<HTML>
<HEAD>
<TITLE>CLHS: Issue DYNAMIC-EXTENT Writeup</TITLE>
<LINK HREF="../Data/clhs.css" REL="stylesheet" TYPE="text/css" />
<META HTTP-EQUIV="Author" CONTENT="Kent M. Pitman">
<META HTTP-EQUIV="Organization" CONTENT="LispWorks Ltd.">
<LINK REL=TOP HREF="../Front/index.htm">
<LINK REL=COPYRIGHT HREF="../Front/Help.htm#Legal">
<LINK REL=DISCLAIMER HREF="../Front/Help.htm#Disclaimer">
<LINK REL=PREV HREF="../Issues/iss141_w.htm">
<LINK REL=UP HREF="../Issues/iss142.htm">
<LINK REL=NEXT HREF="../Issues/iss143_w.htm">
</HEAD>
<BODY>
<H1><A REV=MADE HREF="http://www.lispworks.com/"><IMG WIDTH=80 HEIGHT=65 ALT="[LISPWORKS]" SRC="../Graphics/LWSmall.gif" ALIGN=Bottom></A><A REL=TOP HREF="../Front/index.htm"><IMG WIDTH=237 HEIGHT=65 ALT="[Common Lisp HyperSpec (TM)]" SRC="../Graphics/CLHS_Sm.gif" ALIGN=Bottom></A> <A REL=PREV HREF="../Issues/iss141_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="../Issues/iss142.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="../Issues/iss143_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
<HR>
<H2>Issue DYNAMIC-EXTENT Writeup</H2>
<PRE><B>Status:</B> passed, as amended, Mar 89 X3J13.<P>
<B>Forum:</B> Cleanup<P>
<B>Issue:</B> <A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A><P>
<B>References:</B> Scope and Extent<P>
<B>Category:</B> ADDITION<P>
<B>Edit history:</B> 27-Jun-88, Version 1 by Pitman (as issue STACK-LET)<P>
15-Nov-88, Version 2 by Pitman (issue renamed, major revision)<P>
11-Jan-89, Version 3 by Masinter (Moon's proposal)<P>
05-Apr-89, Version 4 by Pitman and Steele (changes per X3J13)<P>
Related-Issues: REST-ARGUMENT-EXTENT, WITH-DYNAMIC-EXTENT<P>
<P>
<B>Problem Description:<P>
</B><P>
Sometimes a programmer knows that a particular data <A REL=DEFINITION HREF="../Body/f_docume.htm#structure"><B>structure</B></A><P>
will have only dynamic extent. In some implementations, it is<P>
possible to allocate such structures in a way that will make them<P>
easier to reclaim than by general purpose garbage collection<P>
(eg, on the stack or in some temporary area). Currently, however,<P>
there is no way to request the use of such an allocation mechanism.<P>
<P>
<B>Proposal (DYNAMIC-EXTENT:NEW-DECLARATION):<P>
</B><P>
Introduce a new declaration called <A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A>. The arguments to<P>
this declaration are names of variables.<P>
<P>
It is permissible for an implementation to simply ignore this declaration.<P>
In implementations which do not ignore it, the compiler (or interpreter)<P>
is free to make whatever optimizations are appropriate given this<P>
information; the most common optimization is to stack-allocate the<P>
initial value of the object. What data types (if any) can have dynamic<P>
extent will can vary from implementation to implementation.<P>
<P>
Definition: Object &lt;x&gt; is an ``otherwise inaccessible part'' (OIP)<P>
of &lt;y&gt; iff making &lt;y&gt; inaccessible would make &lt;x&gt; inaccessible.<P>
(Note that <A REL=DEFINITION HREF="../Body/f_everyc.htm#every"><B>every</B></A> object is an OIP of itself.)<P>
<P>
Suppose that construct &lt;c&gt; contains a <A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> declaration for<P>
variable &lt;v&gt; (which need not be bound by &lt;c&gt;). Consider the values<P>
&lt;w1&gt;, ..., &lt;wN&gt; taken on by &lt;v&gt; during the course of some execution of<P>
&lt;c&gt;. The declaration asserts that if object &lt;x&gt; is an OIP of &lt;wI&gt;<P>
when &lt;wI&gt; ever becomes the value of &lt;v&gt;, then just after execution of<P>
&lt;c&gt; terminates &lt;x&gt; will be either inaccessible or still an OIP of &lt;v&gt;.<P>
<P>
If the assertion is ever violated, the conseqeuences are undefined.<P>
<P>
<B>Examples:<P>
</B><P>
Since stack allocation of the initial value entails knowing at the<P>
object's creation time that the object can be stack-allocated, it is<P>
not generally useful to declare <A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> for variables for<P>
which have no lexically apparent initial value. For example,<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> F ()<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> ((X (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 1 2 3)))<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X))<P>
...))<P>
<P>
would permit those compilers which wish to do so to stack-allocate the<P>
list in X. However,<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> G (X) (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X)) ...)<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> F () (G (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 1 2 3)))<P>
<P>
could not typically permit a similar optimization in G because it would<P>
be a modularity violation for the compiler to assume facts about G from<P>
within F. Only an implementation which was willing to be responsible for<P>
recompiling F if G's definition changed incompatibly could stack-allocate<P>
the list argument to G in F.<P>
<P>
Other interesting cases are:<P>
<P>
(<A REL=DEFINITION HREF="../Body/f_procla.htm#proclaim"><B>PROCLAIM</B></A> '(<A REL=DEFINITION HREF="../Body/d_inline.htm#inline"><B>INLINE</B></A> G))<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> G (X) (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X)) ...)<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> F () (G (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 1 2 3)))<P>
<P>
and (<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> F ()<P>
(<A REL=DEFINITION HREF="../Body/s_flet_.htm#flet"><B>FLET</B></A> ((G (X) (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X)) ...))<P>
(G (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 1 2 3))))<P>
<P>
where some compilers might realize the optimization was possible and others<P>
might not.<P>
<P>
An interesting variant of this is the so-called `stack allocated rest list'<P>
which can be achieved (in implementations supporting the optimization) by:<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> F (<A REL=DEFINITION HREF="../Body/03_da.htm#AMrest"><B>&amp;REST</B></A> X)<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X))<P>
...)<P>
<P>
Note here that although the initial value of X is not explicit, the F<P>
function is responsible for assembling the list X from the passed arguments,<P>
so the F function can be optimized by the compiler to construct a <P>
stack-allocated list instead of a heap-allocated list in implementations<P>
which support such.<P>
<P>
<P>
In<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> ((X (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 'A1 'B1 'C1))<P>
(Y (<A REL=DEFINITION HREF="../Body/a_cons.htm#cons"><B>CONS</B></A> 'A2 (<A REL=DEFINITION HREF="../Body/a_cons.htm#cons"><B>CONS</B></A> 'B2 (<A REL=DEFINITION HREF="../Body/a_cons.htm#cons"><B>CONS</B></A> 'C2 <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A>)))))<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X Y))<P>
...)<P>
The OIP's of X are three conses, and the OIP's of Y are three other<P>
conses. None of the symbols A1, B1, C1, A2, B2, C2, or <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A> is an<P>
OIP of X or Y. However, if a freshly allocated uninterned symbol had<P>
been used, it would have been an OIP.<P>
<P>
- - - - - - - -<P>
(<A REL=DEFINITION HREF="../Body/m_dotime.htm#dotimes"><B>DOTIMES</B></A> (I N) <P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> I))<P>
<P>
This is particularly instructive. Since I is an integer by the<P>
definition of <A REL=DEFINITION HREF="../Body/m_dotime.htm#dotimes"><B>DOTIMES</B></A>, but <A REL=DEFINITION HREF="../Body/f_eq.htm#eq"><B>EQ</B></A> and <A REL=DEFINITION HREF="../Body/a_eql.htm#eql"><B>EQL</B></A> are not necessarily equivalent for<P>
integers, what are the OIP's of I, which this declaration<P>
requires the body of the <A REL=DEFINITION HREF="../Body/m_dotime.htm#dotimes"><B>DOTIMES</B></A> not to &quot;save&quot;? If the value of I is 3,<P>
and the body does (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO 3), is that an error? The answer is no, but<P>
the interesting thing is that it depends on the implementation-dependent<P>
behavior of <A REL=DEFINITION HREF="../Body/f_eq.htm#eq"><B>EQ</B></A> on numbers. In an implementation where <A REL=DEFINITION HREF="../Body/f_eq.htm#eq"><B>EQ</B></A> and <A REL=DEFINITION HREF="../Body/a_eql.htm#eql"><B>EQL</B></A> are<P>
equivalent for 3, then 3 is not an OIP because (<A REL=DEFINITION HREF="../Body/f_eq.htm#eq"><B>EQ</B></A> I (+ 2 1)) is true,<P>
and therefore there is another way to access the object besides<P>
going through I. On the other hand, in an implementation where <A REL=DEFINITION HREF="../Body/f_eq.htm#eq"><B>EQ</B></A> and<P>
<A REL=DEFINITION HREF="../Body/a_eql.htm#eql"><B>EQL</B></A> are not equivalent for 3, then the particular 3 that is the value of<P>
I is an OIP, but any other 3 is not. Thus (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO 3) is valid<P>
but (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO I) is erroneous. Since (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO I) is erroneous in some<P>
implementations, it is erroneous in all portable programs, but some other<P>
implementations may not be able to detect the error.<P>
<P>
- - - - - - - -<P>
<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> ((X (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 1 2 3)))<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X))<P>
(<A REL=DEFINITION HREF="../Body/f_wr_pr.htm#print"><B>PRINT</B></A> X)<P>
<A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A>)<P>
<A REL=DEFINITION HREF="../Body/f_wr_pr.htm#print"><B>PRINT</B></A> does not &quot;save&quot; any part of its input.<P>
This prints (1 2 3)<P>
<P>
- - - - - - - -<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_do_do.htm#do"><B>DO</B></A> ((L (<A REL=DEFINITION HREF="../Body/f_list_a.htm#list-all-packages"><B>LIST-ALL-PACKAGES</B></A>) (<A REL=DEFINITION HREF="../Body/f_car_c.htm#cdr"><B>CDR</B></A> L)))<P>
((<A REL=DEFINITION HREF="../Body/a_null.htm#null"><B>NULL</B></A> L))<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> L))<P>
(<A REL=DEFINITION HREF="../Body/f_wr_pr.htm#print"><B>PRINT</B></A> (<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> L)))<P>
prints all packages; none of the newly-allocated list structures are saved.<P>
- - - - - - - -<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> ADD (<A REL=DEFINITION HREF="../Body/03_da.htm#AMrest"><B>&amp;REST</B></A> X) (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X)) (<A REL=DEFINITION HREF="../Body/f_apply.htm#apply"><B>APPLY</B></A> #'+ X))<P>
(ADD 1 2 3) =&gt; 6<P>
<P>
I.e., useful way to declare that <A REL=DEFINITION HREF="../Body/03_da.htm#AMrest"><B>&amp;REST</B></A> lists have dynamic extent<P>
- - - - - - - -<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> ZAP (X Y Z)<P>
(<A REL=DEFINITION HREF="../Body/m_do_do.htm#do"><B>DO</B></A> ((L (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> X Y Z) (<A REL=DEFINITION HREF="../Body/f_car_c.htm#cdr"><B>CDR</B></A> L)))<P>
((<A REL=DEFINITION HREF="../Body/a_null.htm#null"><B>NULL</B></A> L))<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> L))<P>
(<A REL=DEFINITION HREF="../Body/f_wr_pr.htm#prin1"><B>PRIN1</B></A> (<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> L))))<P>
(ZAP 1 2 3)<P>
prints 123<P>
<P>
- - - - - - - -<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A> ZAP (N M)<P>
;; Computes (<A REL=DEFINITION HREF="../Body/f_random.htm#random"><B>RANDOM</B></A> (+ M 1)) at relative <A REL=DEFINITION HREF="../Body/d_optimi.htm#speed"><B>speed</B></A> of roughly O(N).<P>
;; It may be slow, but with a good compiler at least it<P>
;; doesn't waste much heap storage. :-)<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> ((A (<A REL=DEFINITION HREF="../Body/f_mk_ar.htm#make-array"><B>MAKE-ARRAY</B></A> N)))<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> A))<P>
(<A REL=DEFINITION HREF="../Body/m_dotime.htm#dotimes"><B>DOTIMES</B></A> (I N) <P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> I))<P>
(<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> (<A REL=DEFINITION HREF="../Body/f_aref.htm#aref"><B>AREF</B></A> A I) (<A REL=DEFINITION HREF="../Body/f_random.htm#random"><B>RANDOM</B></A> (+ I 1))))<P>
(<A REL=DEFINITION HREF="../Body/f_aref.htm#aref"><B>AREF</B></A> A M)))<P>
(&lt; (ZAP 5 3) 3) =&gt; T<P>
<P>
- - - - - - - -<P>
The following are in error, since the value of X is used outside of its<P>
extent:<P>
<P>
(<A REL=DEFINITION HREF="../Body/f_length.htm#length"><B>LENGTH</B></A> (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> (<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> ((X (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 1 2 3))) (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X)) X)))<P>
<P>
(<A REL=DEFINITION HREF="../Body/s_progn.htm#progn"><B>PROGN</B></A> (<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> ((X (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 1 2 3))) (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> (<A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> X)) X)<P>
<A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A>)<P>
<P>
- - - - - - - -<P>
<P>
<B>Rationale:<P>
</B><P>
This permits a programmer to offer advice to an implementation about<P>
what may be stack-allocated for efficiency.<P>
<P>
It may be difficult or impossible for a compiler to infer this<P>
same information statically.<P>
<P>
Since a number of implementations offer this capability and there<P>
is demand from users for access to the capability, this ``codifies<P>
existing practice.''<P>
<P>
Because this approach is purely lexical, it does not interact badly with<P>
other programs in the way that the macro WITH-DYNAMIC-EXTENT (see issue<P>
by same name) would.<P>
<P>
<B>Current Practice:<P>
</B><P>
Symbolics Genera and Symbolics Cloe offer stack allocation, though not<P>
in this strategy.<P>
<P>
[KMP thinks that] Lucid supports the proposal.<P>
<P>
<B>Cost to Implementors:<P>
</B><P>
No cost is forced since implementations are permitted to simply<P>
ignore the <A REL=DEFINITION HREF="../Body/d_dynami.htm#dynamic-extent"><B>DYNAMIC-EXTENT</B></A> declaration.<P>
<P>
<B>Cost to Users:<P>
</B><P>
None. This change is upward compatible.<P>
<P>
There may be some hidden costs to debugging using this declaration (or any<P>
feature which permits the user to access dynamic extent objects without<P>
the compiler proving that they are appropriate). If the user misdeclares<P>
something and returns a pointer into the stack (or stores it in the heap),<P>
an undefined situation may result and the integrity of the Lisp storage<P>
mechanism may be compromised. Debugging these situations may be tricky,<P>
but users who have asked for this feature have indicated a willingness<P>
to deal with such costs. Nevertheless, the perils should be clearly<P>
documented and casual users should not be encouraged to use this<P>
declaration.<P>
<P>
<B>Cost of Non-Adoption:<P>
</B><P>
Some portable code would be forced to run more slowly (due to<P>
GC overhead), or to use non-portable language features.<P>
<P>
<B>Benefits:<P>
</B><P>
The cost of non-adoption is avoided.<P>
<P>
<B>Aesthetics:<P>
</B><P>
This declaration allows a fairly low level optimization to work<P>
by asking the user to <A REL=DEFINITION HREF="../Body/f_provid.htm#provide"><B>provide</B></A> only very high level information.<P>
The alternatives (sharpsign conditionals, some of which may<P>
lead to more bit-picky abstractions) are far less aesthetic.<P>
<P>
<B>Discussion:<P>
</B><P>
A previous version of this proposal suggested primitives STACK-LET<P>
and STACK-LET*. Consensus was that the more general declaration facility<P>
would be more popular.<P>
<P>
Moon came up with a description of something called a &quot;proper part&quot; which<P>
Steele formalized into the idea of an &quot;otherwise inaccessible part&quot;. The<P>
two are essentially interchangeable, but Steele's description was more<P>
rigorous.<P>
<P>
KMP: ... it still raises the question of whether we should define <P>
per-function for every CL function whether any of the arguments is<P>
permitted to be &quot;saved&quot; so that CL programs don't get any funny<P>
surprises. If we don't, it ends up being implementor's discretion how<P>
to resolve cases ... and everyone might not agree that all cases are<P>
... obvious ...<P>
<P>
JonL: PDP10 MacLisp had a similar problem w.r.t pdlnums. That is why<P>
&quot;identity&quot; functions were so troublsome for it -- in order to<P>
return a guaranteed safe value, it typically had to copy it's<P>
pdlnum argument, thereby making some cases of &quot;fast arithmetic&quot; <P>
code much worse than interpreted code! [Remember <A REL=DEFINITION HREF="../Body/f_wr_pr.htm#print"><B>PRINT</B></A> in MacLisp?<P>
it returns T rather than it's argument for just this reason.]<P>
<P>
It is necessary for an optimizing compiler to know something about<P>
what happens to the data it passes along to &quot;system&quot; functions; for<P>
example, it could assume that <A REL=DEFINITION HREF="../Body/f_get.htm#get"><B>GET</B></A> doesn't clobber the list given<P>
to it, nor does it retain pointers to any part of it [what was the<P>
terminology in the revised proposal? &quot;saved&quot;? and &quot;proper part&quot;?]<P>
The issue <A HREF="iss214.htm">LISP-SYMBOL-REDEFINITION</A> might help here, in that an<P>
implementation's compilers could depend upon it's own internal<P>
database. But it wouldn't hurt at all to have some of these<P>
requirements &quot;up front&quot; in the <A REL=DEFINITION HREF="../Body/07_ffb.htm#standard"><B>standard</B></A>.<P>
<P>
It was generally agreed that we would also like to consider a proposal<P>
on dynamic extent functions at the next meeting. (Sandra said she would<P>
prepare one, and has already done so. See issue <A HREF="iss141.htm">DYNAMIC-EXTENT-FUNCTION</A>.)<P>
</PRE>
<HR>
<A REL=NAVIGATOR HREF="../Front/StartPts.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Starting Points]" SRC="../Graphics/StartPts.gif" ALIGN=Bottom></A><A REL=TOC HREF="../Front/Contents.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Contents]" SRC="../Graphics/Contents.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Master.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Index]" SRC="../Graphics/Index.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Symbol.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Symbols]" SRC="../Graphics/Symbols.gif" ALIGN=Bottom></A><A REL=GLOSSARY HREF="../Body/26_a.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Glossary]" SRC="../Graphics/Glossary.gif" ALIGN=Bottom></A><A HREF="../Front/X3J13Iss.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Issues]" SRC="../Graphics/Issues.gif" ALIGN=Bottom></A><BR>
<A REL=COPYRIGHT HREF="../Front/Help.htm#Legal"><I>Copyright 1996-2005, LispWorks Ltd. All rights reserved.</I></A><P>
</BODY>
</HTML>