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

201 lines
13 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 READ-MODIFY-WRITE-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/iss286_w.htm">
<LINK REL=UP HREF="../Issues/iss287.htm">
<LINK REL=NEXT HREF="../Issues/iss288_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/iss286_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="../Issues/iss287.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="../Issues/iss288_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
<HR>
<H2>Issue READ-MODIFY-WRITE-EVALUATION-ORDER Writeup</H2>
<PRE><B>Issue:</B> <A HREF="iss287.htm">READ-MODIFY-WRITE-EVALUATION-ORDER</A><P>
<B>References:</B> <A REL=DEFINITION HREF="../Body/m_defi_2.htm#define-modify-macro"><B>DEFINE-MODIFY-MACRO</B></A><P>
<A REL=DEFINITION HREF="../Body/m_incf_.htm#decf"><B>DECF</B></A>, <A REL=DEFINITION HREF="../Body/m_incf_.htm#incf"><B>INCF</B></A>, <A REL=DEFINITION HREF="../Body/m_pop.htm#pop"><B>POP</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>, <A REL=DEFINITION HREF="../Body/m_remf.htm#remf"><B>REMF</B></A><P>
Related issues: Issue <A HREF="iss312.htm">SETF-SUB-METHODS</A><P>
Issue <A HREF="iss279_m.htm">PUSH-EVALUATION-ORDER</A><P>
<B>Category:</B> Clarification, change<P>
<B>Edit history:</B> v1, 17 Dec 1990, Sandra Loosemore<P>
v2, 19 Feb 1991, Sandra Loosemore<P>
<P>
<P>
<B>Problem description:<P>
</B><P>
Proposal <A HREF="iss312.htm">SETF-SUB-METHODS:DELAYED-ACCESS-STORES</A> states that &quot;reading<P>
the value&quot; of a generalized variable reference is not part of the<P>
series of evaluations that must be done in left-to-right order. That<P>
issue only addressed the problem in the context of <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> places such<P>
as <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>, and <A REL=DEFINITION HREF="../Body/f_mask_f.htm#mask-field"><B>MASK-FIELD</B></A> whose <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> methods include an implicit<P>
read-modify-write operation on a nested place form.<P>
<P>
There is a similar order-of-evaluation issue for explicit<P>
read-modify-write macros such as <A REL=DEFINITION HREF="../Body/m_incf_.htm#incf"><B>INCF</B></A> and those defined with<P>
DEFINE-MODIFY-MACRO: if the access to the place is performed before<P>
other arguments to the macro are evaluated, any side-effects of those<P>
evaluations on the value of the place are lost.<P>
<P>
In the case of <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> of <A REL=DEFINITION HREF="../Body/f_getf.htm#getf"><B>GETF</B></A> and friends, issue <A HREF="iss312.htm">SETF-SUB-METHODS</A> placed<P>
constraints on the order of evaluation of subforms within the values<P>
returned by GET-SETF-METHOD. In the case of <A REL=DEFINITION HREF="../Body/m_incf_.htm#incf"><B>INCF</B></A> and friends, the<P>
question is the order of evaluation in the expansion of the<P>
read-modify-write macro.<P>
<P>
<P>
<B>Proposal READ-MODIFY-WRITE-EVALUATION-ORDER:DELAYED-ACCESS-STORES:<P>
</B><P>
Clarify that the exception of &quot;reading the value&quot; of a generalized<P>
variable reference from the series of evaluations that must be done in<P>
left-to-right order applies to the read-modify-write macros <A REL=DEFINITION HREF="../Body/m_incf_.htm#decf"><B>DECF</B></A>,<P>
<A REL=DEFINITION HREF="../Body/m_incf_.htm#incf"><B>INCF</B></A>, <A REL=DEFINITION HREF="../Body/m_pop.htm#pop"><B>POP</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>, <A REL=DEFINITION HREF="../Body/m_remf.htm#remf"><B>REMF</B></A>, <A REL=DEFINITION HREF="../Body/m_shiftf.htm#shiftf"><B>SHIFTF</B></A> and all macros defined with<P>
<A REL=DEFINITION HREF="../Body/m_defi_2.htm#define-modify-macro"><B>DEFINE-MODIFY-MACRO</B></A>.<P>
<P>
Specifically:<P>
<P>
For <A REL=DEFINITION HREF="../Body/m_incf_.htm#decf"><B>DECF</B></A>, <A REL=DEFINITION HREF="../Body/m_incf_.htm#incf"><B>INCF</B></A>, <A REL=DEFINITION HREF="../Body/m_pop.htm#pop"><B>POP</B></A>, <A REL=DEFINITION HREF="../Body/m_remf.htm#remf"><B>REMF</B></A>, and all macros defined with<P>
DEFINE-MODIFY-MACRO:<P>
<P>
These macros are of the form<P>
(&lt;operator&gt; &lt;place&gt; . &lt;other-arguments&gt;)<P>
The order of evaluation should be:<P>
- all subforms of the &lt;place&gt;, in the order specified by the second<P>
value of GET-SETF-METHOD for that &lt;place&gt;<P>
- the &lt;other-arguments&gt;, in left-to-right order<P>
- the access to &lt;place&gt;<P>
- the computation of the new value to be stored<P>
- the store into &lt;place&gt;<P>
<P>
<P>
For <A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>PUSH</B></A> and PUSHNEW:<P>
<P>
These macros are of the form<P>
(&lt;operator&gt; &lt;object&gt; &lt;place&gt; . &lt;other-arguments&gt;) <P>
The order of evaluation should be:<P>
- the &lt;object&gt;<P>
- all subforms of the &lt;place&gt;, in the order specified by the second<P>
value of GET-SETF-METHOD for that &lt;place&gt;<P>
- the &lt;other-arguments&gt;, in left-to-right order<P>
- the access to &lt;place&gt;<P>
- the computation of the new value to be stored<P>
- the store into &lt;place&gt;<P>
<P>
In other words, the subforms of the &lt;place&gt; argument and any other<P>
argument subforms should be evaluated in left-to-right order, but the<P>
actual access of the &lt;place&gt; happens after all of the subform evaluations<P>
and just before the computation and store of the new value.<P>
<P>
<P>
<B>Examples:<P>
</B><P>
These two examples parallel examples 6 and 7 (respectively) from<P>
issue <A HREF="iss312.htm">SETF-SUB-METHODS</A>.<P>
<P>
1. (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>setq</B></A> r (list 'a 1 'b 2 'c 3))<P>
(<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>setf</B></A> (<A REL=DEFINITION HREF="../Body/f_getf.htm#getf"><B>getf</B></A> r 'b) (<A REL=DEFINITION HREF="../Body/s_progn.htm#progn"><B>progn</B></A> (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>setq</B></A> r <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>nil</B></A>) 6))<P>
r =&gt; (b 6)<P>
<P>
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>setq</B></A> r 5)<P>
(<A REL=DEFINITION HREF="../Body/m_incf_.htm#incf"><B>incf</B></A> r (<A REL=DEFINITION HREF="../Body/s_progn.htm#progn"><B>progn</B></A> (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>setq</B></A> r 0) 1))<P>
r =&gt; 1<P>
<P>
In both cases, the place form that is the target of the read-modify-write<P>
operation is the variable R. The access of this place is delayed until<P>
the other subforms have been evaluated, so the value of R that is<P>
read as part of the read-modify-write operation reflects the <A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A>.<P>
<P>
2. (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>setq</B></A> s (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>setq</B></A> r (list (list 'a 1 'b 2 'c 3))))<P>
(<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>setf</B></A> (<A REL=DEFINITION HREF="../Body/f_getf.htm#getf"><B>getf</B></A> (<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>car</B></A> r) 'b)<P>
(<A REL=DEFINITION HREF="../Body/s_progn.htm#progn"><B>progn</B></A> (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>setq</B></A> r <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>nil</B></A>) 6))<P>
r =&gt; nil<P>
s =&gt; ((A 1 B 6 C 3))<P>
<P>
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>setq</B></A> s (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>setq</B></A> r (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> 5)))<P>
(<A REL=DEFINITION HREF="../Body/m_incf_.htm#incf"><B>incf</B></A> (<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>car</B></A> r) (<A REL=DEFINITION HREF="../Body/s_progn.htm#progn"><B>progn</B></A> (<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>setq</B></A> r (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> 0)) 1))<P>
r =&gt; (0)<P>
s =&gt; (6)<P>
<P>
In both cases, the nested place form is the value of (<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> R). Note that<P>
the <A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> does not affect the read-modify-write operation because the<P>
value of R has already been saved in a temporary variable as part of<P>
evaluating the subforms of the nested place form. The read-modify-write<P>
operation applies to the <A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> of this value.<P>
<P>
<P>
<B>Rationale:<P>
</B><P>
This makes the rules for conceptual &quot;read-modify-write&quot; operations<P>
consistent, regardless of whether or not the operation is specified by<P>
a special-case <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> place (such as <A REL=DEFINITION HREF="../Body/f_getf.htm#getf"><B>GETF</B></A>) or a macro such as those<P>
defined by <A REL=DEFINITION HREF="../Body/m_defi_2.htm#define-modify-macro"><B>DEFINE-MODIFY-MACRO</B></A>.<P>
<P>
<P>
<B>Current Practice:<P>
</B><P>
Neither Lucid CL nor Allegro CL implement this proposal. In both<P>
implementations, the access to the place subform apparently happens in<P>
its normal left-to-right order.<P>
<P>
<P>
<B>Cost to Implementors:<P>
</B><P>
Small.<P>
<P>
<P>
<B>Cost to Users:<P>
</B><P>
Hard to say. Some programs that depend on the strict left-to-right<P>
order of evaluation now supported in some implementations may break,<P>
but probably such programs are no more common than those that were<P>
broken by the adoption of proposal <A HREF="iss312.htm">SETF-SUB-METHODS:DELAYED-ACCESS-STORES</A>.<P>
<P>
<P>
<B>Cost of non-adoption:<P>
</B><P>
Read-modify-write macros such as <A REL=DEFINITION HREF="../Body/m_incf_.htm#incf"><B>INCF</B></A> and macros defined with<P>
<A REL=DEFINITION HREF="../Body/m_defi_2.htm#define-modify-macro"><B>DEFINE-MODIFY-MACRO</B></A> continue to have the same problems with losing<P>
multiple updates to the place that were solved for <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> of <A REL=DEFINITION HREF="../Body/f_getf.htm#getf"><B>GETF</B></A> by<P>
adoption of <A HREF="iss312.htm">SETF-SUB-METHODS:DELAYED-ACCESS-STORES</A>.<P>
<P>
<P>
<B>Performance impact:<P>
</B><P>
Probably not applicable.<P>
<P>
<P>
<B>Benefits:<P>
</B><P>
The cost of non-adoption is avoided. <P>
<P>
<P>
<B>Esthetics:<P>
</B><P>
Specifying the same order of evaluation rules for all conceptual <P>
read-modify-write operations is better than arbitrarily having a <P>
difference between those defined as special-case <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> places (like <A REL=DEFINITION HREF="../Body/f_getf.htm#getf"><B>GETF</B></A>)<P>
and those defined as macros.<P>
<P>
<P>
<B>Discussion:<P>
</B><P>
This proposal does not change the order of evaluation for the macros<P>
<A REL=DEFINITION HREF="../Body/m_rotate.htm#rotatef"><B>ROTATEF</B></A>, <A REL=DEFINITION HREF="../Body/m_shiftf.htm#shiftf"><B>SHIFTF</B></A>, <A REL=DEFINITION HREF="../Body/m_assert.htm#assert"><B>ASSERT</B></A>, <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>. These<P>
macros all have their own peculiar order-of-evaluation rules already.<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>