1
0
Fork 0
cl-sites/HyperSpec-7-0/HyperSpec/Issues/iss279_w.htm
2024-04-01 10:24:07 +02:00

236 lines
18 KiB
HTML

<!-- 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 PUSH-EVALUATION-ORDER 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/iss278_w.htm">
<LINK REL=UP HREF="../Issues/iss279_m.htm">
<LINK REL=NEXT HREF="../Issues/iss281_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/iss278_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="../Issues/iss279_m.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="../Issues/iss281_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
<HR>
<H2>Issue PUSH-EVALUATION-ORDER Writeup</H2>
<PRE><B>Issue:</B> <A HREF="iss279_m.htm">PUSH-EVALUATION-ORDER</A><P>
<B>References:</B> CLtL p. 99 (generalized variables)<P>
p. 270 (<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A>)<P>
All macros that manipulate generalized variables<P>
(<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A>, <A REL=DEFINITION HREF="../Body/m_setf_.htm#psetf"><B>PSETF</B></A>, <A REL=DEFINITION HREF="../Body/f_getf.htm#getf"><B>GETF</B></A>, <A REL=DEFINITION HREF="../Body/m_remf.htm#remf"><B>REMF</B></A>, <A REL=DEFINITION HREF="../Body/m_incf_.htm#incf"><B>INCF</B></A>, <A REL=DEFINITION HREF="../Body/m_incf_.htm#decf"><B>DECF</B></A>, <A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A>, <A REL=DEFINITION HREF="../Body/m_pshnew.htm#pushnew"><B>PUSHNEW</B></A>,<P>
<A REL=DEFINITION HREF="../Body/m_pop.htm#pop"><B>POP</B></A>, <A REL=DEFINITION HREF="../Body/m_check_.htm#check-type"><B>CHECK-TYPE</B></A>, <A REL=DEFINITION HREF="../Body/m_assert.htm#assert"><B>ASSERT</B></A>, <A REL=DEFINITION HREF="../Body/m_tpcase.htm#ctypecase"><B>CTYPECASE</B></A>, <A REL=DEFINITION HREF="../Body/m_case_.htm#ccase"><B>CCASE</B></A>, <A REL=DEFINITION HREF="../Body/m_shiftf.htm#shiftf"><B>SHIFTF</B></A>,<P>
<A REL=DEFINITION HREF="../Body/m_rotate.htm#rotatef"><B>ROTATEF</B></A>, and all macros defined by <A REL=DEFINITION HREF="../Body/m_defi_2.htm#define-modify-macro"><B>DEFINE-MODIFY-MACRO</B></A>).<P>
Issue SETF-FUNCTION-VS-MACRO.<P>
<B>Category:</B> CLARIFICATION<P>
<B>Edit History:</B> Version 1, 15-Oct-87, Jeff Peck<P>
Version 2, 23-Oct-87, Larry Masinter<P>
Version 3, 8-Nov-87, David Moon <P>
Version 4, 14-Nov-87, Larry Masinter <P>
Version 5, 25-Nov-87, Larry Masinter<P>
<P>
<B>Problem Description:<P>
</B><P>
In the form (<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A> (ref1) (<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> (ref2))) It is unclear whether (ref1) should be<P>
evaluated before (ref2). <P>
<P>
CLtL, page 99, in a discussion of generalized variable macros, states: <P>
<P>
&quot;Macros that manipulate generalized variables must guarantee the `obvious'<P>
semantics: subforms of generalized-variable references are evaluated ... in<P>
exactly the same order as they appear in the *source* program. The expansion of<P>
these macros must consist of code that follows these rules or has the same<P>
effect as such code. This is accomplished by introducing temporary variables<P>
bound to the subforms of the reference.&quot;<P>
<P>
This paragraph and a discussion of <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> on the previous pages may also be<P>
interpreted as requiring that *all* subforms of such macro calls should be<P>
evaluated once, in source order, left to right.<P>
<P>
However, CLtL, page 270 states:<P>
<P>
&quot;The effect of (<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A> Item Place) is roughly equivalent to<P>
<P>
(<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> Place (<A REL=DEFINITION HREF="../Body/a_cons.htm#cons"><B>CONS</B></A> Item Place))<P>
<P>
except that the latter would evaluate any subforms of Place twice while <A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A><P>
takes care to evaluate them only once.&quot;<P>
<P>
Place and Item appear in different order in the <A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A> form and the indicated<P>
equivalent <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> form. Should the <A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A> form have primacy over the obvious <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A><P>
form with respect to the left-to-right evaluation?<P>
<P>
Are all subforms in a macro call guaranteed to be evaluated in order, or only<P>
those subforms representing generalized variable references?<P>
<P>
The same question arises for other forms which manipulate generalized variables,<P>
e.g., <A REL=DEFINITION HREF="../Body/m_pshnew.htm#pushnew"><B>PUSHNEW</B></A>, <A REL=DEFINITION HREF="../Body/m_incf_.htm#incf"><B>INCF</B></A>, <A REL=DEFINITION HREF="../Body/m_incf_.htm#decf"><B>DECF</B></A>, and those defined with <A REL=DEFINITION HREF="../Body/m_defi_2.htm#define-modify-macro"><B>DEFINE-MODIFY-MACRO</B></A>.<P>
<P>
Proposal: <A HREF="iss279_m.htm">PUSH-EVALUATION-ORDER:ITEM-FIRST</A><P>
<P>
This proposal is hard to state, although the intent is fairly clear: evalution<P>
proceeds from left to right whenever possible. The left-to-right rule does not<P>
remove the obligation on writers of macros and define-setf-method to ensure<P>
left-to-right order, however. <P>
<P>
In this proposal, a form is something whose syntactic use is such that it will<P>
be evaluated. A &quot;subform&quot; means a form that is nested inside another form -- not<P>
any object nested inside a form regardless of syntactic context. <P>
<P>
(1) The evaluation ordering of subforms within a generalized variable reference<P>
is determined by the order specified by the second value returned by<P>
GET-SETF-METHOD. For all predefined generalized variable references (<A REL=DEFINITION HREF="../Body/f_getf.htm#getf"><B>GETF</B></A>, <A REL=DEFINITION HREF="../Body/f_ldb.htm#ldb"><B>LDB</B></A>),<P>
this order of evaluation is exactly left-to-right. When a generalized variable<P>
reference is derived from a macro expansion, this rule is applied *after* the<P>
macro is expanded to find the appropriate generalized variable reference. <P>
<P>
This is intended to make it clear that if the user writes a <A REL=DEFINITION HREF="../Body/m_defmac.htm#defmacro"><B>DEFMACRO</B></A> or<P>
DEFINE-SETF-METHOD that doesn't preserve order, the the order specified in the<P>
user's code holds; e.g., given <P>
(<A REL=DEFINITION HREF="../Body/m_defmac.htm#defmacro"><B>DEFMACRO</B></A> WRONG-ORDER (X Y) `(<A REL=DEFINITION HREF="../Body/f_getf.htm#getf"><B>GETF</B></A> ,Y ,X))<P>
that (<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A> &lt;value&gt; (WRONG-ORDER &lt;place1&gt; &lt;place2&gt;)).<P>
<P>
will evaluate &lt;place2&gt; first and then &lt;place1&gt; because that is the order they<P>
are evaluated in the macro expansion.<P>
<P>
(2) For the macros that manipulate generalized variables (<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A>, <A REL=DEFINITION HREF="../Body/m_pshnew.htm#pushnew"><B>PUSHNEW</B></A>, <A REL=DEFINITION HREF="../Body/f_getf.htm#getf"><B>GETF</B></A>,<P>
<A REL=DEFINITION HREF="../Body/m_remf.htm#remf"><B>REMF</B></A>, <A REL=DEFINITION HREF="../Body/m_incf_.htm#incf"><B>INCF</B></A>, <A REL=DEFINITION HREF="../Body/m_incf_.htm#decf"><B>DECF</B></A>, <A REL=DEFINITION HREF="../Body/m_shiftf.htm#shiftf"><B>SHIFTF</B></A>, <A REL=DEFINITION HREF="../Body/m_rotate.htm#rotatef"><B>ROTATEF</B></A>, <A REL=DEFINITION HREF="../Body/m_setf_.htm#psetf"><B>PSETF</B></A>, <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A>, <A REL=DEFINITION HREF="../Body/m_pop.htm#pop"><B>POP</B></A>, and those defined with<P>
<A REL=DEFINITION HREF="../Body/m_defi_2.htm#define-modify-macro"><B>DEFINE-MODIFY-MACRO</B></A>) the subforms of the macro call are evaluated exactly once<P>
in left to right order, with the subforms of the generalized variable references<P>
evaluted in the order specified in (1).<P>
<P>
<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A>, <A REL=DEFINITION HREF="../Body/m_pshnew.htm#pushnew"><B>PUSHNEW</B></A>, <A REL=DEFINITION HREF="../Body/f_getf.htm#getf"><B>GETF</B></A>, <A REL=DEFINITION HREF="../Body/m_remf.htm#remf"><B>REMF</B></A>, <A REL=DEFINITION HREF="../Body/m_incf_.htm#incf"><B>INCF</B></A>, <A REL=DEFINITION HREF="../Body/m_incf_.htm#decf"><B>DECF</B></A>, <A REL=DEFINITION HREF="../Body/m_shiftf.htm#shiftf"><B>SHIFTF</B></A>, <A REL=DEFINITION HREF="../Body/m_rotate.htm#rotatef"><B>ROTATEF</B></A>, <A REL=DEFINITION HREF="../Body/m_setf_.htm#psetf"><B>PSETF</B></A>, <A REL=DEFINITION HREF="../Body/m_pop.htm#pop"><B>POP</B></A> evaluate all<P>
subforms before modifying any of the generalized variable locations. <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> (in<P>
the case when the <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> macro has more than two arguments) performs its operation<P>
on each pair in sequence, i.e., in (<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> &lt;place1&gt; &lt;value1&gt; &lt;place2&gt; &lt;value2&gt;<P>
...), the subforms of &lt;place1&gt; and &lt;value1&gt; are evaluated, the location<P>
specified by &lt;place1&gt; is modified to contain the value returned by &lt;value1&gt;, and<P>
then the rest of the <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> form is processed in a like manner.<P>
<P>
(3) For the macros <A REL=DEFINITION HREF="../Body/m_check_.htm#check-type"><B>CHECK-TYPE</B></A>, <A REL=DEFINITION HREF="../Body/m_tpcase.htm#ctypecase"><B>CTYPECASE</B></A>, and <A REL=DEFINITION HREF="../Body/m_case_.htm#ccase"><B>CCASE</B></A>, subforms of the generalized<P>
variable reference are evaluted once as in (1), but may be evaluted again if the<P>
type check files in the case of <A REL=DEFINITION HREF="../Body/m_check_.htm#check-type"><B>CHECK-TYPE</B></A> or none of the cases hold in<P>
<A REL=DEFINITION HREF="../Body/m_tpcase.htm#ctypecase"><B>CTYPECASE</B></A> and <A REL=DEFINITION HREF="../Body/m_case_.htm#ccase"><B>CCASE</B></A>.<P>
<P>
(4) For the macro <A REL=DEFINITION HREF="../Body/m_assert.htm#assert"><B>ASSERT</B></A>, the order of evaluation of the generalized variable<P>
references is not specified. <P>
<P>
(Rules 2, 3 <A REL=DEFINITION HREF="../Body/a_and.htm#and"><B>and</B></A> 4 cover all macros defined in Common Lisp that manupulate<P>
generalized <A REL=DEFINITION HREF="../Body/f_docume.htm#variable"><B>variable</B></A> references.)<P>
<P>
<B>Examples:<P>
</B><P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> ((REF2 (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> '())))<P>
(<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A> (<A REL=DEFINITION HREF="../Body/s_progn.htm#progn"><B>PROGN</B></A> (<A REL=DEFINITION HREF="../Body/f_wr_pr.htm#princ"><B>PRINC</B></A> &quot;1&quot;) 'REF-1)<P>
(<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> (<A REL=DEFINITION HREF="../Body/s_progn.htm#progn"><B>PROGN</B></A> (<A REL=DEFINITION HREF="../Body/f_wr_pr.htm#princ"><B>PRINC</B></A> &quot;2&quot;) REF2))))<P>
<P>
Under this proposal, this would be required to print 12 and not 21.<P>
<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> (X)<P>
(<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A> (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> X (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 'A))<P>
(<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> X (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 'B))))<P>
X)<P>
<P>
; the <A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A> first evalutes (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> X (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 'A)) =&gt; (A)<P>
; then evaluates (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> X (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 'B)) =&gt; (B)<P>
; then modifies the <A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> of (this latest value) to be ((A) . B).<P>
; The result is (((A) . B)). <P>
<P>
<P>
<B>Documentation impact:<P>
</B><P>
<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A> should more appropriately be described as:<P>
<P>
&quot;(<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A> Item Place) is roughly equivalent to (<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> Place (<A REL=DEFINITION HREF="../Body/a_cons.htm#cons"><B>CONS</B></A> Item Place))<P>
except that the subforms of Place are evaluated only once, and Item is evaluated<P>
before Place.&quot;<P>
<P>
The phase &quot;subforms of the reference&quot; which appears several times in CLtL should<P>
be made more specific to be &quot;subforms of the macro call,&quot; referring to the<P>
entire form that calls the generalized-variable manipulating macro.<P>
<P>
<B>Rationale:<P>
</B><P>
This is the unstated intention of the page 97-100 discussion of<P>
generalized-variable referencing macros, and indeed the intended definition of<P>
&quot;obvious semantics&quot; for all macros.<P>
<P>
<B>Current practice:<P>
</B><P>
Many implementations do not currently follow this evaluation order. In the form<P>
(<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A> Item Place), Lucid, Franz, Kyoto and Xerox evaluate Place then Item.<P>
Symbolics evaluates Item then Place.<P>
<P>
<P>
For example, in Franz:<P>
<P>
(<A REL=DEFINITION HREF="../Body/f_mexp_.htm#macroexpand"><B>macroexpand</B></A> '(<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>push</B></A> (ref1) (<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>car</B></A> (ref2))))<P>
<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#letST"><B>LET*</B></A> ((#:G8 (REF2))<P>
(#:G7 (<A REL=DEFINITION HREF="../Body/a_cons.htm#cons"><B>CONS</B></A> (REF1) (<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> #:G8))))<P>
(EXCL::.INV-CAR #:G8 #:G7)) <P>
<P>
In Symbolics Common Lisp, it returns:<P>
<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#letST"><B>LET*</B></A> ((#:G5 (REF1))<P>
(#:G4 (REF2)))<P>
<A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A><P>
(SYS:RPLACA2 #:G4 (<A REL=DEFINITION HREF="../Body/a_values.htm#values"><B>VALUES</B></A> (<A REL=DEFINITION HREF="../Body/a_cons.htm#cons"><B>CONS</B></A> #:G5 (<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> #:G4)))))<P>
<P>
<P>
<B>Cost to implementors:<P>
</B><P>
Minimal, <A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A> etc. could simply be defined by the appropriate macros.<P>
<P>
<B>Cost to users:<P>
</B><P>
No currently portable program should be affected. However, this is a minor<P>
incompatible change for some implementations. No serious performance impact is<P>
expected; while some macro expansions may appear to be more verbose, most<P>
compilers deal reasonably with the required order of evaluation.<P>
<P>
<B>Benefits:<P>
</B><P>
The implementation and semantics of <A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A> become more well specified. This<P>
removes a source of non-portability, abeit likely rare.<P>
<P>
<B>Esthetics:<P>
</B><P>
Common Lisp defines order of evaluation as left-to-right; this clarification<P>
ensures consistency across the language. <P>
<P>
<B>Discussion:<P>
</B><P>
This seems to be the intent of most of the relevant language in CLtL.<P>
<P>
For example, the second to last paragraph on page 99<P>
<P>
&quot;As an example of these semantic rules, in the generalized-variable reference<P>
(<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>setf</B></A> reference value), the value form must be evaluated after all the subforms<P>
of the reference because the value form appears to the right of them.&quot;<P>
<P>
makes it clear that in this context the phrase &quot;generalized-variable reference&quot;<P>
was meant to refer to the entire macro call, not just the Place, and that order<P>
of evaluation rules are not limited to subforms of Places. We hope the<P>
specification should adopt more consistent terminology.<P>
<P>
Note that DEFINE-SETF-METHOD is immune to the exception specified about <A REL=DEFINITION HREF="../Body/m_defmac.htm#defmacro"><B>DEFMACRO</B></A><P>
and DEFINE-SETF-METHOD, because since CLtL p.103 says about DEFINE-SETF-METHOD: <P>
<P>
&quot;This binding permits the body forms to be written without regard for<P>
order-of-evaluation issues.&quot;<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>