From: Harald Hanche-Olsen
Subject: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <pcomypitq8v.fsf@shuttle.math.ntnu.no>
CMUCL seems to think not:

TEST> (setf *print-circle* t)
T
TEST> (let ((list (list nil :a :b)))
        (psetf (cdr list) (cddr list)
               (cddr list) (cdddr list)
               (cdr (cddr list)) (cdr list))
        list)
(NIL . #1=(:B :A . #1#))
TEST> (let ((list (list nil :a :b)))
        (psetf (cdr list) (cddr list)
               (cdr (cdr list)) (cdddr list)
               (cdr (cddr list)) (cdr list))
        list)
(NIL :B :A)

The second of these did what I had expected the first one to do.
Are my expectations wrong?  Maybe I am overly optimistic concerning what
it means to compute a place.  (No need to explain to me what happened
here; a macro expansion demonstrated that just fine, thank you very
much:  Essentially, computing the place (cdddr list) means computing
list, not (cddr list) as I had expected.)

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell

From: Steven M. Haflich
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <47C98C17.6060603@alum.mit.edu>
Harald Hanche-Olsen wrote:
> CMUCL seems to think not:
> 
> TEST> (setf *print-circle* t)
> T
> TEST> (let ((list (list nil :a :b)))
>         (psetf (cdr list) (cddr list)
>                (cddr list) (cdddr list)
>                (cdr (cddr list)) (cdr list))
>         list)
> (NIL . #1=(:B :A . #1#))
> TEST> (let ((list (list nil :a :b)))
>         (psetf (cdr list) (cddr list)
>                (cdr (cdr list)) (cdddr list)
>                (cdr (cddr list)) (cdr list))
>         list)
> (NIL :B :A)

ACL produces the result of your second example for both, and the 
recursive macroexpansion is the same for both forms.  I _think_ the 
behavior is required by the ANS, although this kind of example is 
squirrelly to think about.  A relevant detail is here on the dictionary 
page for setf and psetf:

   For psetf, if more than one pair is supplied then the assignments of
   new values to places are done in parallel. More precisely, all
   subforms (in both the place and newvalue forms) that are to be
   evaluated are evaluated from left to right; after all evaluations
   have been performed, all of the assignments are performed in an
   unpredictable order.

But psetf is required to compute all the new values and all the conses 
that will have their cdrs modified before doing any modification.  So 
the "unpredictable" order in which the cdrs are changed should not matter.

One way to explore this further would be to evaluate these forms on 
CMUCL.  The details will be implementation dependent, but they shold be 
effectively the same.  On ACL:

cl-user(10): (get-setf-expansion '(cdr (cddr x)))
(#:g40)
((cddr x))
(#:g39)
(excl::.inv-cdr #:g40 #:g39)
(cdr #:g40)
cl-user(11): (get-setf-expansion '(cdddr x))
(#:g42)
((cddr x))
(#:g41)
(excl::.inv-cdr #:g42 #:g41)
(cdr #:g42)
From: Brian Adkins
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <ab81bdf5-8d10-489a-9378-6478447fc7c7@z17g2000hsg.googlegroups.com>
On Mar 1, 12:02 pm, "Steven M. Haflich" <····@alum.mit.edu> wrote:
> Harald Hanche-Olsen wrote:
> > CMUCL seems to think not:
>
> > TEST> (setf *print-circle* t)
> > T
> > TEST> (let ((list (list nil :a :b)))
> >         (psetf (cdr list) (cddr list)
> >                (cddr list) (cdddr list)
> >                (cdr (cddr list)) (cdr list))
> >         list)
> > (NIL . #1=(:B :A . #1#))
> > TEST> (let ((list (list nil :a :b)))
> >         (psetf (cdr list) (cddr list)
> >                (cdr (cdr list)) (cdddr list)
> >                (cdr (cddr list)) (cdr list))
> >         list)
> > (NIL :B :A)
>
> ACL produces the result of your second example for both, and the
> recursive macroexpansion is the same for both forms.  I _think_ the
> behavior is required by the ANS, although this kind of example is
> squirrelly to think about.  A relevant detail is here on the dictionary
> page for setf and psetf:
>
>    For psetf, if more than one pair is supplied then the assignments of
>    new values to places are done in parallel. More precisely, all
>    subforms (in both the place and newvalue forms) that are to be
>    evaluated are evaluated from left to right; after all evaluations
>    have been performed, all of the assignments are performed in an
>    unpredictable order.
>
> But psetf is required to compute all the new values and all the conses
> that will have their cdrs modified before doing any modification.  So
> the "unpredictable" order in which the cdrs are changed should not matter.
>
> One way to explore this further would be to evaluate these forms on
> CMUCL.  The details will be implementation dependent, but they shold be
> effectively the same.  On ACL:
>
> cl-user(10): (get-setf-expansion '(cdr (cddr x)))
> (#:g40)
> ((cddr x))
> (#:g39)
> (excl::.inv-cdr #:g40 #:g39)
> (cdr #:g40)
> cl-user(11): (get-setf-expansion '(cdddr x))
> (#:g42)
> ((cddr x))
> (#:g41)
> (excl::.inv-cdr #:g42 #:g41)
> (cdr #:g42)

sbcl: (also gives same result as CMUCL (unsurprisingly) as OP)

* (get-setf-expansion '(cdr (cddr x)))

(#:G1475)
((CDDR X))
(#:G1474)
(SB-KERNEL:%RPLACD #:G1475 #:G1474)
(CDR #:G1475)
* (get-setf-expansion '(cdddr x))

(#:G1476)
(X)
(#:G1477)
(SB-KERNEL:%RPLACD (CDDR #:G1476) #:G1477)
(CDDDR #:G1476)

clisp: (also gives same result as ACL for OP)

[1]> (get-setf-expansion '(cdr (cddr x)))
(#:G8166) ;
((CDDR X)) ;
(#:G8165) ;
(SYSTEM::%RPLACD #:G8166 #:G8165) ;
(CDR #:G8166)
[2]> (get-setf-expansion '(cdddr x))
(#:G8167) ;
(X) ;
(#:G8168) ;
(SYSTEM::%RPLACD (CDDR #:G8167) #:G8168) ;
(CDDDR #:G8167)
From: Barry Margolin
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <barmar-6A939C.12404501032008@comcast.dca.giganews.com>
In article 
<····································@z17g2000hsg.googlegroups.com>,
 Brian Adkins <···········@gmail.com> wrote:

> sbcl: (also gives same result as CMUCL (unsurprisingly) as OP)
> 
> * (get-setf-expansion '(cdr (cddr x)))
> 
> (#:G1475)
> ((CDDR X))
> (#:G1474)
> (SB-KERNEL:%RPLACD #:G1475 #:G1474)
> (CDR #:G1475)
> * (get-setf-expansion '(cdddr x))
> 
> (#:G1476)
> (X)
> (#:G1477)
> (SB-KERNEL:%RPLACD (CDDR #:G1476) #:G1477)
> (CDDDR #:G1476)
> 
> clisp: (also gives same result as ACL for OP)
> 
> [1]> (get-setf-expansion '(cdr (cddr x)))
> (#:G8166) ;
> ((CDDR X)) ;
> (#:G8165) ;
> (SYSTEM::%RPLACD #:G8166 #:G8165) ;
> (CDR #:G8166)
> [2]> (get-setf-expansion '(cdddr x))
> (#:G8167) ;
> (X) ;
> (#:G8168) ;
> (SYSTEM::%RPLACD (CDDR #:G8167) #:G8168) ;
> (CDDDR #:G8167)

Are you implying that there's a difference between SBCL/CMUCL and 
CLISP/ACL?  I don't see any difference, other than the name of the 
internal package containing %RPLACD.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Brian Adkins
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <9ce00fb1-4f67-4109-986c-6b080e60e82a@b1g2000hsg.googlegroups.com>
On Mar 1, 12:40 pm, Barry Margolin <······@alum.mit.edu> wrote:
> In article
> <····································@z17g2000hsg.googlegroups.com>,
>  Brian Adkins <···········@gmail.com> wrote:
>
>
>
> > sbcl: (also gives same result as CMUCL (unsurprisingly) as OP)
>
> > * (get-setf-expansion '(cdr (cddr x)))
>
> > (#:G1475)
> > ((CDDR X))
> > (#:G1474)
> > (SB-KERNEL:%RPLACD #:G1475 #:G1474)
> > (CDR #:G1475)
> > * (get-setf-expansion '(cdddr x))
>
> > (#:G1476)
> > (X)
> > (#:G1477)
> > (SB-KERNEL:%RPLACD (CDDR #:G1476) #:G1477)
> > (CDDDR #:G1476)
>
> > clisp: (also gives same result as ACL for OP)
>
> > [1]> (get-setf-expansion '(cdr (cddr x)))
> > (#:G8166) ;
> > ((CDDR X)) ;
> > (#:G8165) ;
> > (SYSTEM::%RPLACD #:G8166 #:G8165) ;
> > (CDR #:G8166)
> > [2]> (get-setf-expansion '(cdddr x))
> > (#:G8167) ;
> > (X) ;
> > (#:G8168) ;
> > (SYSTEM::%RPLACD (CDDR #:G8167) #:G8168) ;
> > (CDDDR #:G8167)
>
> Are you implying that there's a difference between SBCL/CMUCL and
> CLISP/ACL?

CLISP & SBCL give different results for the OP's snippets
From: Steven M. Haflich
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <47C9CAE5.8050609@alum.mit.edu>
Brian Adkins wrote:

> [1]> (get-setf-expansion '(cdr (cddr x)))
> (#:G8166) ;
> ((CDDR X)) ;
> (#:G8165) ;
> (SYSTEM::%RPLACD #:G8166 #:G8165) ;
> (CDR #:G8166)
> [2]> (get-setf-expansion '(cdddr x))
> (#:G8167) ;
> (X) ;
> (#:G8168) ;
> (SYSTEM::%RPLACD (CDDR #:G8167) #:G8168) ;
> (CDDDR #:G8167)

I'm not sure I understand.  ACL gave effectively the same result for 
these two examples, but the above two results are not the equivalent 
under psetf.  I can't quite find definitive text in the ANS, but my 
intuition is that [2] above is nonconformant since it delays evaluating 
some subforms of the `place' that will be modified by psetf, until the 
time the modification is to take place:

   (SYSTEM::%RPLACD (CDDR #:G8167) #:G8168)

The place subform (cdr #:g8167) has not yet been evaluated.  The 
expansion form I believe would be correct is

   cl-user(11): (get-setf-expansion '(cdddr x))
   (#:g42)
   ((cddr x))
   (#:g41)
 > (excl::.inv-cdr #:g42 #:g41)
   (cdr #:g42)

because the action of the setf form (flagged) is independent on what may 
have already happened to the cdr of #:g42, there as the rplacd (cddr 
#:G8167) form presumably depends upon anything that has already happened 
to (cdr #:g8167), meaning the place has not yet been fully determined.
From: Harald Hanche-Olsen
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <pcolk516wi0.fsf@shuttle.math.ntnu.no>
+ "Steven M. Haflich" <···@alum.mit.edu>:

> A relevant detail is here on the dictionary page for setf and psetf:
>
>   For psetf, if more than one pair is supplied then the assignments of
>   new values to places are done in parallel. More precisely, all
>   subforms (in both the place and newvalue forms) that are to be
>   evaluated are evaluated from left to right; after all evaluations
>   have been performed, all of the assignments are performed in an
>   unpredictable order.
>
> But psetf is required to compute all the new values and all the conses
> that will have their cdrs modified before doing any modification.

Well, note that it talks of /subforms/ here.  And the only subform of
(cddr list) is list, while (cdr (cdr list)) obviously has the subform
(cdr list).  So I think a literal reading of CLHS can justify the
behaviour of cmucl and sbcl.

Indeed, sbcl implements (setf cddr) as

(defsetf cddr (x) (v) `(%rplacd (cdr ,x) ,v))

whereas my first thought was that it should be something like this:
["First thought" is kind of an exaggeration; I had to read up on
define-setf-expander before I could write this]

(define-setf-expander cddr (x)
  (let ((place (gensym))
	(store (gensym)))
    (values `(,place)
	    `((cdr ,x))
	    `(,store)
	    `(%rplacd ,place ,store)
	    `(cdr ,place))))

... and similarly for the other c*r forms, of course.

But then, an overly (?) literal reading of CLHS could indeed lead to the
belief that this is not permitted, and that ACL is therefore in the
wrong.  OTOH, I really do think that my code, or the behaviour of ACL,
is more useful.  Though it seems fraught with danger to try to rely on
it, obviously.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: Steven M. Haflich
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <47CAEBF3.2080608@alum.mit.edu>
Harald Hanche-Olsen wrote:

> (defsetf cddr (x) (v) `(%rplacd (cdr ,x) ,v))
> 
> whereas my first thought was that it should be something like this:
> ["First thought" is kind of an exaggeration; I had to read up on
> define-setf-expander before I could write this]
> 
> (define-setf-expander cddr (x)
>   (let ((place (gensym))
> 	(store (gensym)))
>     (values `(,place)
> 	    `((cdr ,x))
> 	    `(,store)
> 	    `(%rplacd ,place ,store)
> 	    `(cdr ,place))))

I don't know what %rplacd does (it isn't standard CL) but unless it is 
equivalent to (cdr (rplacd ... ...)) neither of the above definitions 
are correct.  The storing form must return the new value.  This point is 
made explicitly with reference to rplaca in the ANS page for defsetf.
From: Harald Hanche-Olsen
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <pcolk51ovay.fsf@shuttle.math.ntnu.no>
+ "Steven M. Haflich" <···@alum.mit.edu>:

> I don't know what %rplacd does (it isn't standard CL) but unless it is
> equivalent to (cdr (rplacd ... ...))

It is.  That is the reason for its existence.

> The storing form must return the new value.  This point is made
> explicitly with reference to rplaca in the ANS page for defsetf.

Indeed.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: Kent M Pitman
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <uir04vn4y.fsf@nhplace.com>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

> + "Steven M. Haflich" <···@alum.mit.edu>:
> 
> > I don't know what %rplacd does (it isn't standard CL) but unless it is
> > equivalent to (cdr (rplacd ... ...))
> 
> It is.  That is the reason for its existence.

And the reason for its naming? :)

It's admittedly a small point, but personally I might have called it
set-cdr, just for clarity, to avoid precisely that confusion.

FWIW, %rplacd as a name sounds to me like a low-error-checking version
of rplacd that will otherwise provide the same function.  That is, it
sounds like the kind of thing I'd use to rplacd a fixnum ... a common
practice in MACLISP, by the way, with quite interesting and useful, if
not perspicuous, effects.  Btw, if you're curious about that, see:
http://groups.google.com/group/comp.lang.lisp/msg/47a158c459fa4ec2?
From: Harald Hanche-Olsen
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <pcoprucbvz2.fsf@shuttle.math.ntnu.no>
+ Kent M Pitman <······@nhplace.com>:

> Harald Hanche-Olsen <······@math.ntnu.no> writes:
>
>> + "Steven M. Haflich" <···@alum.mit.edu>:
>> 
>> > I don't know what %rplacd does (it isn't standard CL) but unless it is
>> > equivalent to (cdr (rplacd ... ...))
>> 
>> It is.  That is the reason for its existence.
>
> And the reason for its naming? :)

Heh.  I spoke out of turn, perhaps.  I didn't write %rplaca, nor did I
name it.  So it's really not my place (pun intended) to say what it's
for or why it's named that way.

> FWIW, %rplacd as a name sounds to me like a low-error-checking version
> of rplacd that will otherwise provide the same function.

Agreed.  In the SBCL source it says:

;;; The following are for use by SETF.

(defun %rplaca (x val) (rplaca x val) val)

(defun %rplacd (x val) (rplacd x val) val)

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: Barry Margolin
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <barmar-28CFD1.18520602032008@newsgroups.comcast.net>
In article <···············@shuttle.math.ntnu.no>,
 Harald Hanche-Olsen <······@math.ntnu.no> wrote:

> + Kent M Pitman <······@nhplace.com>:
> 
> > Harald Hanche-Olsen <······@math.ntnu.no> writes:
> >
> >> + "Steven M. Haflich" <···@alum.mit.edu>:
> >> 
> >> > I don't know what %rplacd does (it isn't standard CL) but unless it is
> >> > equivalent to (cdr (rplacd ... ...))
> >> 
> >> It is.  That is the reason for its existence.
> >
> > And the reason for its naming? :)
> 
> Heh.  I spoke out of turn, perhaps.  I didn't write %rplaca, nor did I
> name it.  So it's really not my place (pun intended) to say what it's
> for or why it's named that way.
> 
> > FWIW, %rplacd as a name sounds to me like a low-error-checking version
> > of rplacd that will otherwise provide the same function.
> 
> Agreed.  In the SBCL source it says:
> 
> ;;; The following are for use by SETF.
> 
> (defun %rplaca (x val) (rplaca x val) val)
> 
> (defun %rplacd (x val) (rplacd x val) val)

Are there any compiler optimizers for it?  Or maybe the compiler 
recognizes it specially and open-codes it.  That's a common reason for 
internal %functions.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Kent M Pitman
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <u1w6sfx74.fsf@nhplace.com>
Barry Margolin <······@alum.mit.edu> writes:

> > ;;; The following are for use by SETF.
> > 
> > (defun %rplaca (x val) (rplaca x val) val)
> > 
> > (defun %rplacd (x val) (rplacd x val) val)
> 
> Are there any compiler optimizers for it?  Or maybe the compiler 
> recognizes it specially and open-codes it.  That's a common reason for 
> internal %functions.

On the LispM, I seem to recall being told that the % functions (which
are mostly the low level memory system and whatnot) were so-named
because of the bootstrapping issue that there was no package system at
some point and so early symbols want to not get accidentally clobbered
before there is a package system to protect them.  (The 1979 black
chinual had tv-beep rather than tv:beep, if I recall.)  That was
common in pre-package system days.  My guess is they should have gone
back and put all those symbols in another package rather than have
them share a namespace with other symbols that could accidentally
clobber them.

An extreme case was the Programmer's Apprentice at MIT (which had Dick
Waters of iteration and pretty printer fame working on it, btw), where
the way program modules were separated was by a leading digit.  So
every function in that very large system was something like 5ASSERT or
8DEFINE or something, and it wasn't a typo--it was a primitive package
system that didn't have to worry about whether it was running in the
LispM (which had a package system) or MACLISP (which didn't).
From: Barry Margolin
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <barmar-C9E505.22232402032008@newsgroups.comcast.net>
In article <·············@nhplace.com>,
 Kent M Pitman <······@nhplace.com> wrote:

> Barry Margolin <······@alum.mit.edu> writes:
> 
> > > ;;; The following are for use by SETF.
> > > 
> > > (defun %rplaca (x val) (rplaca x val) val)
> > > 
> > > (defun %rplacd (x val) (rplacd x val) val)
> > 
> > Are there any compiler optimizers for it?  Or maybe the compiler 
> > recognizes it specially and open-codes it.  That's a common reason for 
> > internal %functions.
> 
> On the LispM, I seem to recall being told that the % functions (which
> are mostly the low level memory system and whatnot) were so-named
> because of the bootstrapping issue that there was no package system at
> some point and so early symbols want to not get accidentally clobbered
> before there is a package system to protect them.  (The 1979 black
> chinual had tv-beep rather than tv:beep, if I recall.)  That was
> common in pre-package system days.  My guess is they should have gone
> back and put all those symbols in another package rather than have
> them share a namespace with other symbols that could accidentally
> clobber them.

Perhaps that was the original reason.  By the time I started using 
Lispms, I think it had turned into a naming convention comparable to 
*...* for special variables.  The % functions were the ones you had to 
be very careful when using, because they were the low-level primitives 
that usually corresponded directly to machine instructions, and could 
violate the language spec.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Harald Hanche-Olsen
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <pcozltgxpn2.fsf@shuttle.math.ntnu.no>
+ Barry Margolin <······@alum.mit.edu>:

> In article <···············@shuttle.math.ntnu.no>,
>  Harald Hanche-Olsen <······@math.ntnu.no> wrote:
>
>> Agreed.  In the SBCL source it says:
>> 
>> ;;; The following are for use by SETF.
>> 
>> (defun %rplaca (x val) (rplaca x val) val)
>> 
>> (defun %rplacd (x val) (rplacd x val) val)
>
> Are there any compiler optimizers for it?

Not as far as I can tell, though for all I know there may be magic that
I cannot see, not being very familiar with SBCL internals.  To me, it
looks like they're just rplaca and rplacd with different return values
for the purpose of being more usable in setf expanders.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: Juho Snellman
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <871w6rbn4f.fsf@vasara.proghammer.com>
Harald Hanche-Olsen <······@math.ntnu.no> writes:
> >> (defun %rplacd (x val) (rplacd x val) val)
> >
> > Are there any compiler optimizers for it?
> 
> Not as far as I can tell, though for all I know there may be magic that
> I cannot see, not being very familiar with SBCL internals.

There is a bit of magic involved, as should be obvious from RPLACD
being defined in terms of (SETF CDR), (SETF CDR) defined in terms of
%RPLACD, %RPLACD being in terms of RPLACD :-) The circular definition
is broken by %RPLACD actually being a compile primitive for setting
the CDR (defined in src/compiler/generic/objdef.lisp), that defun is
there just for cases where a non-opencoded definition is needed.

-- 
Juho Snellman
From: Harald Hanche-Olsen
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <pcofxv7vasv.fsf@shuttle.math.ntnu.no>
+ Juho Snellman <······@iki.fi>:

> There is a bit of magic involved,

Aha.  So is that a convention in sbcl, that functions named %whatever
are magical like this?  I guess it could explain some things I have
encountered in the sources that didn't make sens to me.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: Barry Margolin
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <barmar-2AF00E.00552404032008@newsgroups.comcast.net>
In article <···············@shuttle.math.ntnu.no>,
 Harald Hanche-Olsen <······@math.ntnu.no> wrote:

> + Juho Snellman <······@iki.fi>:
> 
> > There is a bit of magic involved,
> 
> Aha.  So is that a convention in sbcl, that functions named %whatever
> are magical like this?  I guess it could explain some things I have
> encountered in the sources that didn't make sens to me.

Probably not just SBCL.  I think in many implementations, %whatever are 
the primitives that the compiler always open-codes.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Juho Snellman
Subject: Re: Should (cdddr x) and (cdr (cddr x)) be the same place?
Date: 
Message-ID: <87r6eqabfy.fsf@vasara.proghammer.com>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

> + Juho Snellman <······@iki.fi>:
> 
> > There is a bit of magic involved,
> 
> Aha.  So is that a convention in sbcl, that functions named %whatever
> are magical like this?

Not really. There are functions that don't have a % prefix which are
handled specially by the compiler (starting with a large proportion of
the symbols in CL), and there are functions with a % prefix that the
compiler has no special knowledge of. It might be more of a "%foo is
something used to implement foo" convention.

-- 
Juho Snellman
From: Harald Hanche-Olsen
Subject: define-setf-expander
Date: 
Message-ID: <pcohcfp6vzl.fsf_-_@shuttle.math.ntnu.no>
+ Harald Hanche-Olsen <······@math.ntnu.no>:

> ["First thought" is kind of an exaggeration; I had to read up on
> define-setf-expander before I could write this]
>
> (define-setf-expander cddr (x)
>   (let ((place (gensym))
> 	(store (gensym)))
>     (values `(,place)
> 	    `((cdr ,x))
> 	    `(,store)
> 	    `(%rplacd ,place ,store)
> 	    `(cdr ,place))))

Actually, if I were to emulate the examples given in the description of
define-setf-expander in CLHS, I should probably have used the value of
(get-setf-expansion x) in the above code.  But I don't understand why.
I mean, even if the argument where another macro call or something like
that, it would be taken care of after the current call to (setf cddr)
was expanded, would it not?  Can anyone enlighten me?

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: Kalle Olavi Niemitalo
Subject: Re: define-setf-expander
Date: 
Message-ID: <87mypg3jv7.fsf@Astalo.kon.iki.fi>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

> Actually, if I were to emulate the examples given in the description of
> define-setf-expander in CLHS, I should probably have used the value of
> (get-setf-expansion x) in the above code.  But I don't understand why.

It seems to me the first example could have been written without
GET-SETF-EXPANDER:

  (define-setf-expander lastguy2 (list-form &environment env)
    "Set the last element in a list to the given value."
    (let ((last (gensym)) (store (gensym)))
      (values `(,last)
              `((last ,list-form))
              `(,store)
              `(progn (rplaca ,last ,store) ,store)
              `(car ,last))))

or alternatively:

  (define-setf-expander lastguy3 (list-form &environment env)
    "Set the last element in a list to the given value."
    (let ((list (gensym)) (store (gensym)))
      (values `(,list)
              `(,list-form)
              `(,store)
              `(progn (rplaca (last ,list) ,store) ,store)
              `(lastguy ,list))))

These changes alter the behaviour of the setf expander however,
in that the variants save different parts of the structure into
temporary variables.  The differences can be detected:

  (let* ((tree (copy-tree '((1 (2)) (3 (4)))))
         (node (car tree)))
    (psetf (car tree) (cadr tree)
           (cdr node) (list 4)
           (lastguy (car tree)) 5)
    (list tree node))

At least with SBCL 0.9.5.50, this returns different values for
the different setf expanders:

(((3 5) (3 5)) (1 4)) for LASTGUY,
(((3 (4)) (3 (4))) (1 4)) for LASTGUY2,
(((3 (4)) (3 (4))) (1 5)) for LASTGUY3.

I don't see any obvious reason to consider one of these results
correct and the others wrong.  Users of places should avoid
depending on such details of setf expanders.

In the LDB example however, GET-SET-EXPANSION is necessary
because the storing form of the setf expansion of the LDB form
must invoke the storing form of the setf expansion of the INT
parameter.

(let ((x (vector 0)))
  (setf (ldb (byte 2 4) (aref x 0)) 3)
  x)
;; => #(48)

The setf expansion of (aref x 0) is needed here.
From: Harald Hanche-Olsen
Subject: Re: define-setf-expander
Date: 
Message-ID: <pcolk50bvrn.fsf@shuttle.math.ntnu.no>
+ Kalle Olavi Niemitalo <···@iki.fi>:

> Harald Hanche-Olsen <······@math.ntnu.no> writes:
>
>> Actually, if I were to emulate the examples given in the description of
>> define-setf-expander in CLHS, I should probably have used the value of
>> (get-setf-expansion x) in the above code.  But I don't understand why.
>
> It seems to me the first example could have been written without
> GET-SETF-EXPANDER:

Ah, good.  So it's not only me, then.

> I don't see any obvious reason to consider one of these results
> correct and the others wrong.  Users of places should avoid depending
> on such details of setf expanders.

Good advice, obviously.

> In the LDB example however, GET-SET-EXPANSION is necessary
> because the storing form of the setf expansion of the LDB form
> must invoke the storing form of the setf expansion of the INT
> parameter.

Yes, that is suddenly obvious.  Thank you.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell