320 lines
24 KiB
HTML
320 lines
24 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 REMF-DESTRUCTION-UNSPECIFIED 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/iss292_w.htm">
|
|
<LINK REL=UP HREF="../Issues/iss293.htm">
|
|
<LINK REL=NEXT HREF="../Issues/iss294_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/iss292_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="../Issues/iss293.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="../Issues/iss294_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
|
|
|
|
<HR>
|
|
|
|
|
|
|
|
<H2>Issue REMF-DESTRUCTION-UNSPECIFIED Writeup</H2>
|
|
|
|
<PRE><B>Status:</B> v6 accepted by X3J13 with amendments to fix typos (see v7) on 16-1 vote<P>
|
|
<B>Issue:</B> <A HREF="iss293.htm">REMF-DESTRUCTION-UNSPECIFIED</A><P>
|
|
<B>References:</B> (<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> (<A REL=DEFINITION HREF="../Body/f_get.htm#get"><B>GET</B></A> ...) ...), <A REL=DEFINITION HREF="../Body/f_rempro.htm#remprop"><B>REMPROP</B></A>, (<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> ...) ...),<P>
|
|
<A REL=DEFINITION HREF="../Body/m_remf.htm#remf"><B>REMF</B></A> (pp165-167); <A REL=DEFINITION HREF="../Body/f_revers.htm#nreverse"><B>NREVERSE</B></A> (p248); <A REL=DEFINITION HREF="../Body/f_rm_rm.htm#delete"><B>DELETE</B></A>, <A REL=DEFINITION HREF="../Body/f_rm_rm.htm#delete-if"><B>DELETE-IF</B></A>,<P>
|
|
<A REL=DEFINITION HREF="../Body/f_rm_dup.htm#delete-duplicates"><B>DELETE-DUPLICATES</B></A>, <A REL=DEFINITION HREF="../Body/f_sbs_s.htm#nsubstitute"><B>NSUBSTITUTE</B></A>, <A REL=DEFINITION HREF="../Body/f_sbs_s.htm#nsubstitute-if"><B>NSUBSTITUTE-IF</B></A> (pp254-256); <P>
|
|
<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A>, <A REL=DEFINITION HREF="../Body/f_revapp.htm#nreconc"><B>NRECONC</B></A> (p269); <A REL=DEFINITION HREF="../Body/f_unionc.htm#nunion"><B>NUNION</B></A>, <A REL=DEFINITION HREF="../Body/f_isec_.htm#nintersection"><B>NINTERSECTION</B></A>,<P>
|
|
<A REL=DEFINITION HREF="../Body/f_set_ex.htm#nset-exclusive-or"><B>NSET-EXCLUSIVE-OR</B></A> (pp276-279).<P>
|
|
<B>Category:</B> CLARIFICATION/CHANGE<P>
|
|
<B>Edit history:</B> 11-Feb-87, Version 1 by Dave Andre (DLA@Symbolics.COM)<P>
|
|
29-Oct-87, Version 2 by Pitman (flesh out proposals)<P>
|
|
28-Nov-88, Version 3 by Pitman (revised presentation)<P>
|
|
29-Nov-88, Version 4 by Pitman (slight editing per DLA)<P>
|
|
15-Mar-89, Version 5 by Margolin (amendments discussed in<P>
|
|
Hawaii, removed -NOT functions)<P>
|
|
17-Mar-89, Version 6 by Margolin (make NSUBSTITUTE* less vague)<P>
|
|
05-Apr-89, Version 7 by Pitman (typos corrected per X3J13)<P>
|
|
<P>
|
|
<B>Problem Description:<P>
|
|
</B><P>
|
|
Currently, the exact nature of the side-effect performed by list<P>
|
|
modification routines is not specified.<P>
|
|
<P>
|
|
Either the specific modifications allowed should be specified so that<P>
|
|
programmers can rely on them and implementors can avoid accidentally<P>
|
|
causing problems by introducing well-meaning optimizations, or else<P>
|
|
the documentation should explicitly state that the effects are<P>
|
|
unspecified so that programmers will not depend on them and <P>
|
|
implementors will feel comfortable about doing interesting optimizations.<P>
|
|
<P>
|
|
<B>Proposal (REMF-DESTRUCTION-UNSPECIFIED:X3J13-MAR-89):<P>
|
|
</B><P>
|
|
Clarify that the way in which the destructive behavior of the<P>
|
|
operators below is achieved is explicitly vague in a number of ways,<P>
|
|
in order to <A REL=DEFINITION HREF="../Body/f_provid.htm#provide"><B>provide</B></A> individual implementations the necessary<P>
|
|
flexibility to do useful optimizations.<P>
|
|
<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> place indicator) value)<P>
|
|
is permitted to either <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> place or to <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> any part, <A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> or<P>
|
|
<A REL=DEFINITION HREF="../Body/f_car_c.htm#cdr"><B>CDR</B></A>, of the top-level list <A REL=DEFINITION HREF="../Body/f_docume.htm#structure"><B>structure</B></A> held by that place.<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_remf.htm#remf"><B>REMF</B></A> place indicator)<P>
|
|
is permitted to either <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> place or to <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> any part, <A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> or<P>
|
|
<A REL=DEFINITION HREF="../Body/f_car_c.htm#cdr"><B>CDR</B></A>, of the top-level list <A REL=DEFINITION HREF="../Body/f_docume.htm#structure"><B>structure</B></A> held by that place.<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> (<A REL=DEFINITION HREF="../Body/f_get.htm#get"><B>GET</B></A> <A REL=DEFINITION HREF="../Body/t_symbol.htm#symbol"><B>symbol</B></A> indicator) value)<P>
|
|
is constrained to behave exactly the same as<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_symb_4.htm#symbol-plist"><B>SYMBOL-PLIST</B></A> symbol) indicator) value).<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_rempro.htm#remprop"><B>REMPROP</B></A> <A REL=DEFINITION HREF="../Body/t_symbol.htm#symbol"><B>symbol</B></A> indicator)<P>
|
|
is constrained to behave exactly the same as<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_remf.htm#remf"><B>REMF</B></A> (<A REL=DEFINITION HREF="../Body/f_symb_4.htm#symbol-plist"><B>SYMBOL-PLIST</B></A> symbol) indicator).<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_revers.htm#nreverse"><B>NREVERSE</B></A> <A REL=DEFINITION HREF="../Body/t_seq.htm#sequence"><B>sequence</B></A>)<P>
|
|
when sequence is a list, is permitted to <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> any part, <A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> or<P>
|
|
<A REL=DEFINITION HREF="../Body/f_car_c.htm#cdr"><B>CDR</B></A>, of the top-level list <A REL=DEFINITION HREF="../Body/f_docume.htm#structure"><B>structure</B></A> in that sequence.<P>
|
|
when sequence is an array is permitted to re-order the elements<P>
|
|
of the given sequence in order to produce the resulting array.<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_rm_rm.htm#delete"><B>DELETE</B></A> object <A REL=DEFINITION HREF="../Body/t_seq.htm#sequence"><B>sequence</B></A> ...)<P>
|
|
when sequence is a list, is permitted to <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> any part, <A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> or<P>
|
|
<A REL=DEFINITION HREF="../Body/f_car_c.htm#cdr"><B>CDR</B></A>, of the top-level list <A REL=DEFINITION HREF="../Body/f_docume.htm#structure"><B>structure</B></A> held in that sequence.<P>
|
|
when sequence is an array is permitted to change the dimensions<P>
|
|
of the array and to slide its elements into new positions without<P>
|
|
permuting them to produce the resulting array.<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_rm_rm.htm#delete-if"><B>DELETE-IF</B></A> test <A REL=DEFINITION HREF="../Body/t_seq.htm#sequence"><B>sequence</B></A> ...)<P>
|
|
is constrained to behave exactly like<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_rm_rm.htm#delete"><B>DELETE</B></A> <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A> <A REL=DEFINITION HREF="../Body/t_seq.htm#sequence"><B>sequence</B></A><P>
|
|
:TEST #'(<A REL=DEFINITION HREF="../Body/a_lambda.htm#lambda"><B>LAMBDA</B></A> (<A REL=DEFINITION HREF="../Body/d_ignore.htm#ignore"><B>IGNORE</B></A> ITEM) (<A REL=DEFINITION HREF="../Body/f_funcal.htm#funcall"><B>FUNCALL</B></A> test ITEM))<P>
|
|
...).<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_rm_dup.htm#delete-duplicates"><B>DELETE-DUPLICATES</B></A> <A REL=DEFINITION HREF="../Body/t_seq.htm#sequence"><B>sequence</B></A> ...)<P>
|
|
when sequence is a list, is permitted to <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> any part, <A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> or<P>
|
|
<A REL=DEFINITION HREF="../Body/f_car_c.htm#cdr"><B>CDR</B></A>, of the top-level list <A REL=DEFINITION HREF="../Body/f_docume.htm#structure"><B>structure</B></A> held in that sequence.<P>
|
|
when sequence is an array is permitted to change the dimensions<P>
|
|
of the array and to slide its elements into new positions without<P>
|
|
permuting them to produce the resulting array.<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_revapp.htm#nreconc"><B>NRECONC</B></A> <A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> tail)<P>
|
|
is constrained to have side-effect behavior equivalent to:<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> (<A REL=DEFINITION HREF="../Body/f_revers.htm#nreverse"><B>NREVERSE</B></A> list) tail).<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_unionc.htm#nunion"><B>NUNION</B></A> list1 list2 ...)<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_isec_.htm#nintersection"><B>NINTERSECTION</B></A> list1 list2 ...)<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_set_ex.htm#nset-exclusive-or"><B>NSET-EXCLUSIVE-OR</B></A> list1 list2 ...)<P>
|
|
is permitted to <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> any part, <A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> or <A REL=DEFINITION HREF="../Body/f_car_c.htm#cdr"><B>CDR</B></A>, of the top-level of<P>
|
|
any of the given lists.<P>
|
|
<P>
|
|
Note, however, that since this side-effect is not required,<P>
|
|
these functions should still not be used in for-effect-only<P>
|
|
positions in portable code.<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> . lists)<P>
|
|
is defined using the following recursive relationship:<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A>) => <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A><P>
|
|
(<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A> . args) == (<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> . args)<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> arg) => arg<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> arg1 arg2) has the side effect of (<A REL=DEFINITION HREF="../Body/f_rplaca.htm#rplacd"><B>RPLACD</B></A> (<A REL=DEFINITION HREF="../Body/f_last.htm#last"><B>LAST</B></A> arg1) arg2),<P>
|
|
and returns arg1 <P>
|
|
(<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> arg1 arg2 . args) == (<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> (<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> arg1 arg2) . args)<P>
|
|
<P>
|
|
[If a previous cleanup issue prohibited <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A> as a non-last argument<P>
|
|
then ignore the (<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A> . args) case.]<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_sbs_s.htm#nsubstitute"><B>NSUBSTITUTE</B></A> new-object old-object <A REL=DEFINITION HREF="../Body/t_seq.htm#sequence"><B>sequence</B></A> ...)<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_sbs_s.htm#nsubstitute-if"><B>NSUBSTITUTE-IF</B></A> new-object test <A REL=DEFINITION HREF="../Body/t_seq.htm#sequence"><B>sequence</B></A> ...)<P>
|
|
is required to <A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>SETF</B></A> any <A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> (if <A REL=DEFINITION HREF="../Body/t_seq.htm#sequence"><B>SEQUENCE</B></A> is a list) or <A REL=DEFINITION HREF="../Body/f_aref.htm#aref"><B>AREF</B></A> (if it's<P>
|
|
a vector) of <A REL=DEFINITION HREF="../Body/t_seq.htm#sequence"><B>SEQUENCE</B></A> which is required to be replaced with<P>
|
|
NEW-OBJECT. If <A REL=DEFINITION HREF="../Body/t_seq.htm#sequence"><B>SEQUENCE</B></A> is a list, none of the CDRs of the<P>
|
|
top-level list may be modified. These functions, therefore, may be<P>
|
|
used in for-effect-only positions in code (some may find this<P>
|
|
stylistically distasteful, though).<P>
|
|
<P>
|
|
Note: The above clarifications are not intended as complete functional<P>
|
|
descriptions. They are intended to augment (rather than to replace)<P>
|
|
other descriptions already in effect.<P>
|
|
<P>
|
|
<B>Test Cases:<P>
|
|
</B><P>
|
|
For <A REL=DEFINITION HREF="../Body/f_getf.htm#getf"><B>GETF</B></A>...<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 'A 'B 'C 'D 'E 'F)) ==> (A B C D E F)<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> BAR (<A REL=DEFINITION HREF="../Body/f_car_c.htm#cddr"><B>CDDR</B></A> FOO)) ==> (C D E F)<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_remf.htm#remf"><B>REMF</B></A> FOO 'C)<P>
|
|
BAR ==> ??<P>
|
|
<P>
|
|
In Symbolics Common Lisp, BAR holds (C D E F).<P>
|
|
CLtL allows other interpretations. eg, BAR might hold<P>
|
|
(C), (<A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A>), (C <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A>) or (C D).<P>
|
|
Under this proposal, any of these interpretations (and others as well)<P>
|
|
would still be valid<P>
|
|
<P>
|
|
For <A REL=DEFINITION HREF="../Body/f_rm_rm.htm#delete"><B>DELETE</B></A>...<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 'A 'B 'C)) ==> (A B C)<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> BAR (<A REL=DEFINITION HREF="../Body/f_car_c.htm#cdr"><B>CDR</B></A> FOO)) ==> (B C)<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO (<A REL=DEFINITION HREF="../Body/f_rm_rm.htm#delete"><B>DELETE</B></A> 'B FOO)) ==> (A C)<P>
|
|
BAR ==> ??<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_eq.htm#eq"><B>EQ</B></A> (<A REL=DEFINITION HREF="../Body/f_car_c.htm#cdr"><B>CDR</B></A> FOO) (<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> BAR)) ==> ??<P>
|
|
<P>
|
|
In Symbolics Common Lisp, these last two expressions return ((C)) and T.<P>
|
|
Under this proposal, either of these interpretations (and others<P>
|
|
as well) would be valid.<P>
|
|
<P>
|
|
For <A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A>...<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 'A 'B 'C 'D 'E)<P>
|
|
BAR (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 'F 'G 'H 'I 'J)<P>
|
|
BAZ (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 'K 'L 'M)) => (K L M)<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO (<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> FOO BAR BAZ)) => (A B C D E F G H I J K L M)<P>
|
|
FOO => (A B C D E F G H I J K L M)<P>
|
|
BAR => (F G H I J K L M)<P>
|
|
BAZ => (K L M)<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 'A 'B 'C 'D 'E)<P>
|
|
BAR (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 'F 'G 'H 'I 'J)<P>
|
|
BAZ (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> 'K 'L 'M)) => (K L M)<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> FOO (<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A> FOO BAR <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A> BAZ)) => (A B C D E F G H I J K L M) <P>
|
|
FOO => (A B C D E F G H I J K L M)<P>
|
|
BAR => (F G H I J K L M)<P>
|
|
BAZ => (K L M)<P>
|
|
<P>
|
|
<P>
|
|
<B>Rationale:<P>
|
|
</B><P>
|
|
Implementations already vary widely on their implementation techniques<P>
|
|
for these functions. This effectively clarifies the status quo, making<P>
|
|
it more clear to programmers what they may rely upon in portable code.<P>
|
|
<P>
|
|
In the case of <A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A>, however, the precise definition is useful because<P>
|
|
it is what users expect, it is how <A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> has been defined for many<P>
|
|
years, and it is how current implementations generally work. It may<P>
|
|
not always be the most efficient way (e.g. it may result in invisible<P>
|
|
pointers in CDR-coded implementations), but callers of <A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> probably<P>
|
|
use it specifically for its precise side effects.<P>
|
|
<P>
|
|
In the case of <A REL=DEFINITION HREF="../Body/f_sbs_s.htm#nsubstitute"><B>NSUBSTITUTE</B></A>, this seems like the only reasonable<P>
|
|
implementation mechanism, and there doesn't seem to be a reason not to<P>
|
|
guarantee it.<P>
|
|
<P>
|
|
<B>Current Practice:<P>
|
|
</B><P>
|
|
All valid implementations are believed to comply with the vague<P>
|
|
definitions. Symbolics Genera 7.2 and Sun Common Lisp 2.1.3 appear to<P>
|
|
conform to the <A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> spec.<P>
|
|
<P>
|
|
<B>Cost to Implementors:<P>
|
|
</B><P>
|
|
None. This is probably the status quo for most implementors. If there<P>
|
|
are any implementations that don't implement <A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> and <A REL=DEFINITION HREF="../Body/f_sbs_s.htm#nsubstitute"><B>NSUBSTITUTE</B></A> as<P>
|
|
above (which I doubt) they will have to be changed.<P>
|
|
<P>
|
|
<B>Cost to Users:<P>
|
|
</B><P>
|
|
This change would not affect programs coded with "good programming<P>
|
|
practice". That is, only programs which rely on currently undocumented<P>
|
|
features would be in any danger of breaking. In fact, those programs<P>
|
|
are already in such danger, and this change to the documentation would<P>
|
|
just publicize it. The clarification would -encourage- good programming<P>
|
|
practice by warning people to only obey the published contract of the<P>
|
|
above-mentioned functions.<P>
|
|
<P>
|
|
There is, however, no automatic technique for making this check for<P>
|
|
programs already in error. Bugs due to unexpected side-effects are in<P>
|
|
general among the hardest to reckon with.<P>
|
|
<P>
|
|
<B>Cost of Non-Adoption:<P>
|
|
</B><P>
|
|
Programmers may naively believe there is only one possible or reasonable<P>
|
|
implementation of these functions. Some implementors may shy away from<P>
|
|
reasonable optimizations out of a paranoid belief that deviating from <P>
|
|
some vague, unspoken rules will lead to programmer unrest. Making these<P>
|
|
things explicitly vague clarifies the implementor's rights in a way that<P>
|
|
permits numerous useful optimizations.<P>
|
|
<P>
|
|
<B>Benefits: <P>
|
|
</B><P>
|
|
Users would be discouraged from taking advantage of subtle details<P>
|
|
of these destructive operations because such details would be explicitly<P>
|
|
not guaranteed to be portable.<P>
|
|
<P>
|
|
Implementations can improve performance of many of the above-mentioned<P>
|
|
functions when they are not under the constraint to implement them<P>
|
|
in a highly constrained fashion. For example, in Symbolics systems,<P>
|
|
<A REL=DEFINITION HREF="../Body/f_rm_rm.htm#delete"><B>DELETE</B></A> of a cdr-coded list could use the implementation primitive<P>
|
|
%CHANGE-LIST-TO-CONS rather than <A REL=DEFINITION HREF="../Body/f_rplaca.htm#rplacd"><B>RPLACD</B></A> to avoid creating forwarding<P>
|
|
pointers.<P>
|
|
<P>
|
|
Garbage collection effectiveness can also be improved. For example,<P>
|
|
all of the destructive operations which remove objects (eg, <A REL=DEFINITION HREF="../Body/m_remf.htm#remf"><B>REMF</B></A>)<P>
|
|
could remove <A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> pointers to removed objects which are more volatile<P>
|
|
than the list itself, assisting the garbage collector and thereby<P>
|
|
improving memory usage and paging performance.<P>
|
|
<P>
|
|
Tightening the definition of <A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> and <A REL=DEFINITION HREF="../Body/f_sbs_s.htm#nsubstitute"><B>NSUBSTITUTE</B></A> permits users to<P>
|
|
predict their programs' behavior more precisely.<P>
|
|
<P>
|
|
<B>Non-Benefits:<P>
|
|
</B><P>
|
|
Users who inadvertently depend on side-effect behavior may be rudely<P>
|
|
surprised when moving between implementations.<P>
|
|
<P>
|
|
Compatibility with older Lisp dialects is diminished.<P>
|
|
<P>
|
|
Implementors have less flexibility in implementing <A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> efficiently.<P>
|
|
This is true of <A REL=DEFINITION HREF="../Body/f_sbs_s.htm#nsubstitute"><B>NSUBSTITUTE</B></A>, but this is less likely to cause problems.<P>
|
|
<P>
|
|
<B>Performance Impact:<P>
|
|
</B><P>
|
|
Metering in Symbolics test systems have shown that there are substantial<P>
|
|
performance gains to be had by allowing implementations flexibility in<P>
|
|
these areas.<P>
|
|
<P>
|
|
In the case of <A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A>, this implementation flexibility, and hence<P>
|
|
potential performance improvements, is sacrificed.<P>
|
|
<P>
|
|
If anyone ever invents CAR-coding, the required implementation of<P>
|
|
<A REL=DEFINITION HREF="../Body/f_sbs_s.htm#nsubstitute"><B>NSUBSTITUTE</B></A> could be a performance hindrance.<P>
|
|
<P>
|
|
<B>Aesthetics:<P>
|
|
</B><P>
|
|
Most of these functions implement abstract operations. For example,<P>
|
|
<A REL=DEFINITION HREF="../Body/f_rempro.htm#remprop"><B>REMPROP</B></A> implements an abstract operation on a "property list".<P>
|
|
Proper language design should not encourage people to delve below the<P>
|
|
level of abstraction into the nitty gritty.<P>
|
|
<P>
|
|
<A REL=DEFINITION HREF="../Body/f_nconc.htm#nconc"><B>NCONC</B></A> is a "less abstract" function than the rest of the functions<P>
|
|
described above. It is usually used precisely because of the way it<P>
|
|
interacts with list implementation. Similarly for <A REL=DEFINITION HREF="../Body/f_sbs_s.htm#nsubstitute"><B>NSUBSTITUTE</B></A>.<P>
|
|
<P>
|
|
<B>Discussion:<P>
|
|
</B><P>
|
|
Andre's original version of this proposal pushed for explicitly vague<P>
|
|
descriptions of these functions' side-effect behavior. He believes<P>
|
|
that if users want more predictability from these functions, they<P>
|
|
should write private variants that implement whatever predictability<P>
|
|
they <A REL=DEFINITION HREF="../Body/f_provid.htm#require"><B>require</B></A>. <P>
|
|
<P>
|
|
Pitman originally opposed this position because he weighed portability<P>
|
|
a higher concern. Since the original discussion, however, his views on<P>
|
|
how to resolve this priority have been refined, and he now believes<P>
|
|
that leaving things vague is appropriate. As such, he now supports what<P>
|
|
is effectively Andre's original proposal.<P>
|
|
<P>
|
|
Pitman and Andre supported version 4. [I don't know how they feel<P>
|
|
about v6 -- Barmar].<P>
|
|
<P>
|
|
Moon supports version 6.<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>
|