Hi, I am a newcomer to lisp, and confused by the rplacd evaluation
process in following scenario:
first initial the x and y as:
(setq x (list 'p 'q))
=> (P Q)
(setq y (list (list 'a 'b) x 'foo x))
=>((A B) (P Q) FOO (P Q))
then why
(rplacd (last y) (cdr y))
is different from
(rplacd (last y) '((A B) (P Q) FOO (P Q)) )
where y get the recursive result, in my understanding, in the former
case:
((a b) . #1=(#2=(p q) foo #2# . #1#))
and in the later case:
((A B) (P Q) FOO (P Q) (A B) (P Q) FOO (P Q))
Thanks for your being patient to answer such question.
First, I presume you are doing this to learn handling conses, lists,
etc.; with the exception of learning and experimentation, destructive
operations like RPLACD are rarely needed, and when they are, must be
used with sufficient care. That said:
On Fri, 26 Jun 2009 22:52:32 -0700 (PDT), lisphus <·······@gmail.com> said:
> ...
> (rplacd (last y) (cdr y))
Before reading further, draw the list in box-and-arrow notation
before and after the call to RPLACD so that you will understand what
happens here. You will see that you are changing the (regular) list
into a circular list, by "plugging" what was its tail terminator
into its second node.
In words (which work worse than a box-and-arrow drawing, which I
hope you have drawn already with your own hand as the most effective
way to achieve understanding), (LAST Y) gives you an arrow pointing
to the last cons cell of Y, (CDR Y) gives you an arrow pointing to
the second cons cell of Y (a "copy" of the arrow that connects the
first box of Y to the second box of Y), and then RPLACD
changes---destructively, i.e. in place---a part of the (LAST Y) box
so that instead of a terminator, now there is an arrow (that same
"copy" mentioned above) going out of its right-hand half and
pointing to the (CDR Y) box.
I put "copy" in quotes, because only the arrow is "copied", _not_
the box to which it points.
In the notation of the Common Lisp printer, when it detects and
shows circularities:
* (setf *print-circle* t)
T
* (let ((y (list 0 1 2))) (rplacd (last y) (cdr y)) y)
(0 . #1=(1 2 . #1#))
so this is "logically" the infinite list (0 1 2 1 2 1 2 ...).
> (rplacd (last y) '((A B) (P Q) FOO (P Q)) )
This simply makes the list longer (destructively, but not
circularly).
---Vassil.
--
Vassil Nikolov <········@pobox.com>
(1) M(Gauss);
(2) M(a) if M(b) and declared(b, M(a)),
where M(x) := "x is a mathematician".
On Jun 27, 2:50 pm, Vassil Nikolov <········@pobox.com> wrote:
> First, I presume you are doing this to learn handling conses, lists,
> etc.; with the exception of learning and experimentation, destructive
> operations like RPLACD are rarely needed, and when they are, must be
> used with sufficient care. That said:
>
> On Fri, 26 Jun 2009 22:52:32 -0700 (PDT), lisphus <·······@gmail.com> said:
>
> > ...
> > (rplacd (last y) (cdr y))
>
> Before reading further, draw the list in box-and-arrow notation
> before and after the call to RPLACD so that you will understand what
> happens here. You will see that you are changing the (regular) list
> into a circular list, by "plugging" what was its tail terminator
> into its second node.
>
> In words (which work worse than a box-and-arrow drawing, which I
> hope you have drawn already with your own hand as the most effective
> way to achieve understanding), (LAST Y) gives you an arrow pointing
> to the last cons cell of Y, (CDR Y) gives you an arrow pointing to
> the second cons cell of Y (a "copy" of the arrow that connects the
> first box of Y to the second box of Y), and then RPLACD
> changes---destructively, i.e. in place---a part of the (LAST Y) box
> so that instead of a terminator, now there is an arrow (that same
> "copy" mentioned above) going out of its right-hand half and
> pointing to the (CDR Y) box.
>
> I put "copy" in quotes, because only the arrow is "copied", _not_
> the box to which it points.
>
> In the notation of the Common Lisp printer, when it detects and
> shows circularities:
>
> * (setf *print-circle* t)
> T
> * (let ((y (list 0 1 2))) (rplacd (last y) (cdr y)) y)
> (0 . #1=(1 2 . #1#))
>
> so this is "logically" the infinite list (0 1 2 1 2 1 2 ...).
>
> > (rplacd (last y) '((A B) (P Q) FOO (P Q)) )
>
> This simply makes the list longer (destructively, but not
> circularly).
>
> ---Vassil.
>
> --
> Vassil Nikolov <········@pobox.com>
>
> (1) M(Gauss);
> (2) M(a) if M(b) and declared(b, M(a)),
> where M(x) := "x is a mathematician".
Thanks for your detailed explanation!
Because I've never gotten aware of the box-arrow representation of the
cons, and it's linked list, right? I am now clear about it and will
pay attention to the terms difference to C language which I am used to.
lisphus <·······@gmail.com> wrote:
+---------------
| Because I've never gotten aware of the box-arrow representation of the
| cons, and it's linked list, right? I am now clear about it and will
| pay attention to the terms difference to C language which I am used to.
+---------------
Note that you can use box & arrow notation just as fruitfully
in C as in Lisp (and probably should try doing so now that you
know about it).
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
From: Pascal J. Bourguignon
Subject: Re: ask for help: confusion about rplacd
Date:
Message-ID: <877hyyw0ul.fsf@galatea.local>
lisphus <·······@gmail.com> writes:
> Hi, I am a newcomer to lisp, and confused by the rplacd evaluation
> process in following scenario:
>
> first initial the x and y as:
> (setq x (list 'p 'q))
> => (P Q)
> (setq y (list (list 'a 'b) x 'foo x))
> =>((A B) (P Q) FOO (P Q))
>
> then why
> (rplacd (last y) (cdr y))
> is different from
> (rplacd (last y) '((A B) (P Q) FOO (P Q)) )
>
> where y get the recursive result, in my understanding, in the former
> case:
> ((a b) . #1=(#2=(p q) foo #2# . #1#))
>
> and in the later case:
> ((A B) (P Q) FOO (P Q) (A B) (P Q) FOO (P Q))
Here is the situation in memory after:
(setq x (list 'p 'q))
(setq y (list (list 'a 'b) x 'foo x))
(read-from-string "((A B) (P Q) FOO (P Q))")
+-----------------------------------------------------------------------+
| +--- Y (LAST Y) -----+ |
| | | |
| v v |
| +---+---+ +---+---+ +---+---+ +---+---+ |
| | * | * |-->| * | * |-->| * | * |-->| * |NIL| |
| +---+---+ +---+---+ +---+---+ +---+---+ |
| | | | | |
| | | +-----------------------------+ |
| | | | | |
| | | | | |
| | +----------+ +----------+ | |
| | | | | |
| | | | | |
| v v v | |
| +---+---+ +---+---+ +---+---+ +---+---+ | |
| | * | * |-->| * |NIL| | * | * |-->| * |NIL| | |
| +---+---+ +---+---+ +---+---+ +---+---+ | |
| | | | | | |
| v v v v v |
| +---+ +---+ +---+ +---+ +-----+ |
| | A | | B | | P | | Q | | FOO | |
| +---+ +---+ +---+ +---+ +-----+ |
| ^ ^ ^ ^ ^ ^ ^ |
| | | | | | | | |
| +---+---+ +---+---+ | | | | | |
| | * | * |-->| * |NIL| | | | | | |
| +---+---+ +---+---+ | +---+ | +----------+ | |
| ^ | | | | | |
| | +----------+ | | | | |
| | | | | | | |
| | | +----------+ | | |
| | | | | | | |
| | | | +------+ | | |
| | | | | | | |
| | +---+---+ +---+---+ | | | |
| | | * | * |-->| * |NIL| | | | |
| | +---+---+ +---+---+ | | | |
| | ^ | | | |
| | | | | | |
| | | +-----------------------------+ |
| | | | | | |
| | | | | | |
| | | | +---+---+ +---+---+ |
| | | | | * | * |-->| * |NIL| |
| | | | +---+---+ +---+---+ |
| | | | ^ |
| | | | | |
| +---+---+ +---+---+ +---+---+ +---+---+ |
| | * | * |-->| * | * |-->| * | * |-->| * |NIL| |
| +---+---+ +---+---+ +---+---+ +---+---+ |
| ^ |
| | |
| ((A B) (P Q) FOO (P Q)) |
+-----------------------------------------------------------------------+
Now modify the arrows to reflect the results after either:
(rplacd (last y) (cdr y)) or:
(rplacd (last y) '((A B) (P Q) FOO (P Q)))
--
__Pascal Bourguignon__
From: Pascal J. Bourguignon
Subject: Re: ask for help: confusion about rplacd
Date:
Message-ID: <87y6rdvbtn.fsf@galatea.local>
Alberto Riva <·····@nospam.ufl.edu> writes:
> Just curious... do you draw these diagrams by hand, or do you have
> some kind of tool you use to produce them?
http://darcs.informatimago.com/lisp/common-lisp/cons-to-ascii.lisp
and emacs picture-mode.
--
__Pascal Bourguignon__
Pascal J. Bourguignon wrote:
> Alberto Riva <·····@nospam.ufl.edu> writes:
>> Just curious... do you draw these diagrams by hand, or do you have
>> some kind of tool you use to produce them?
>
> http://darcs.informatimago.com/lisp/common-lisp/cons-to-ascii.lisp
> and emacs picture-mode.
Right, I remembered you had something like that, but I couldn't find it
anymore... thanks!
Alberto
On 2009-06-27, lisphus <·······@gmail.com> wrote:
> Hi, I am a newcomer to lisp, and confused by the rplacd evaluation
> process in following scenario:
>
> first initial the x and y as:
> (setq x (list 'p 'q))
>=> (P Q)
> (setq y (list (list 'a 'b) x 'foo x))
>=>((A B) (P Q) FOO (P Q))
>
> then why
> (rplacd (last y) (cdr y))
> is different from
> (rplacd (last y) '((A B) (P Q) FOO (P Q)) )
(CDR Y) is the second cons cell of the list stored in Y. So what you are doing
here is installing the second cons cell of a list in place of the NIL which
terminates that list. By installing something from the front of a list to the
end, you create a cycle.
On the other hand, '((A B) (P Q) FOO (P Q)) is a totally different object,
which just /looks/ like what is originally in Y. It has the same list structure
shape as the list Y, and the same symbols in the leaves. But it shares no list
structure with Y; all of the conses in this list are different objects. By
installing this at the end, we are replacing the NIL terminator of Y with brand
new material that simply makes the list longer. We are not sticking a piece of
Y at the end of Y, and thus not creating a cycle.
You can verify this:
;; Y is not the literal '((A B) ...) but a different object:
(EQ Y '((A B) (P Q) FOO (P Q))) -> NIL
;; However, Y is EQUAL to such a literal:
(EQUAL y '((A B) (P Q) FOO (P Q))) -> T
> where y get the recursive result, in my understanding, in the former
> case:
> ((a b) . #1=(#2=(p q) foo #2# . #1#))
So here you have the *PRINT-CIRCLE* notation showing you two things:
that your list is circular (the tail section identified by . #1=
appears as the tail . #1#) and that the two pieces (P Q) are the
same object, denoted by #2=(P Q) and a later occurence of #2#.
The two (P Q) occurences are the same object because they came from the
multiple evaluation of X: (list ... x 'foo 'x).