Lisp HUG Maillist Archive

Circular data-structures not printing correctly?

If I :

(setq p (list 1 2 3 4))

then,

(setq p (rplaca (cons 5 p) (cadddr p)))

shouldn't I get a circular data structure involving at least one "#1=" ?
Instead I get a "flat" data structure.

Randall Blanchard
blancha2@earthlink.net



Re: Circular data-structures not printing correctly?

On 9/2/08, Randall Blanchard <blancha2@earthlink.net> wrote:
> If I :
>
> (setq p (list 1 2 3 4))
>
> then,
>
> (setq p (rplaca (cons 5 p) (cadddr p)))
>
> shouldn't I get a circular data structure involving at least one "#1=" ?
> Instead I get a "flat" data structure.

Normally, you only get that kind of output when *print-circle* is
bound to a non-NIL value (which is not the default because of the
computational overhead involved).

Bye,

Erik.


Re: Circular data-structures not printing correctly?

Randall Blanchard wrote:
> If I :
> 
> (setq p (list 1 2 3 4))
> 
> then,
> 
> (setq p (rplaca (cons 5 p) (cadddr p)))
> 
> shouldn't I get a circular data structure involving at least one "#1=" ?

No. You're creating a new pair, and changing the car of that pair to 4. 
There's no shared cons cell, much less any circularity. Sharing atoms is 
not sharing structure requiring #n=

-- 
Chris Riesbeck

Home page: http://www.cs.northwestern.edu/~riesbeck/
Calendar: http://calendar.yahoo.com/criesbeck


Re: Circular data-structures not printing correctly?

Chris Riesbeck writes:
> 
> Randall Blanchard wrote:
> > If I :
> > 
> > (setq p (list 1 2 3 4))
> > 
> > then,
> > 
> > (setq p (rplaca (cons 5 p) (cadddr p)))
> > 
> > shouldn't I get a circular data structure involving at least one "#1=" ?
> 
> No. You're creating a new pair, and changing the car of that pair to 4. 
> There's no shared cons cell, much less any circularity. Sharing atoms is 
> not sharing structure requiring #n=

However, in the case of non interned atoms, #= references are still
used when *PRINT-CIRCLE*.


C/USER[37]> (let* ((a (list 'a #\+ 1 "i" #(b #\- 2 "ii")))
                   (b (append a a))
                   (*print-circle* t))
              (print b)
              (values))

(A #\+ 1 #1="i" #2=#(B #\- 2 "ii") A #\+ 1 #1# #2#) 

C/USER[38]> 


The reason is that symbols, characters and numbers are immutable, and
reading twice the same (string=) representation gives always the same
(eql) object.


C/USER[43]> (every (lambda (s) (eql (read-from-string s) (read-from-string s))) 
                    '("1" "a" "#\\c"))
T

Therefore there's no need to refer explicitely to the previous
occurence.



On the other hand, other atoms (most of them are not even atomic), are
mutable, and not interned in anyways. Reading their representation
again produces a distinct copy:

C/USER[45]> (some (lambda (s) (eql (read-from-string s) (read-from-string s))) 
                  '("\"a\"" "#(a b c)" "#*10101010"))
NIL

So for these objects, it may be important to distinguish references to
a unique objects, from occurence of a copy:



C/USER[51]> (let* ((a (list (make-string 3 :initial-element #\a)))
                   (b (append a a (list (make-string 3 :initial-element #\a)))))
              (let ((*print-circle* t))   (print b))
              (let ((*print-circle* nil)) (print b))
              (setf (aref (car a) 0) #\X)
              (let ((*print-circle* t))   (print b))
              (let ((*print-circle* nil)) (print b))
              (values))

(#1="aaa" #1# "aaa") 
("aaa" "aaa" "aaa") 
(#1="Xaa" #1# "aaa") 
("Xaa" "Xaa" "aaa") 

C/USER[52]> 



Oh, and finally, here is how you can make a circular list:

C/USER[52]> (setf *print-circle* t)
T
C/USER[53]> (let ((a (list 1 2 3)))
              (rplacd (last a) a) ; notice that (last a) returns the last CONS cell.
              a)
#1=(1 2 3 . #1#)
C/USER[54]> 


Or a random circular structure:

C/USER[55]> (let ((a (list 1 2 3)))
              (rplaca (cdr a) a) ; notice that (cdr a) returns aCONS cell..
              a)
#1=(1 #1# 3)

C/USER[56]> (setf *print-circle* nil *print-length* nil *print-level* 4)
4
C/USER[57]> (let ((a (list 1 2 3)))
              (rplaca (cdr a) a) ; notice that (cdr a) returns aCONS cell..
              a)
(1 (1 (1 (1 # 3) 3) 3) 3)
C/USER[58]> 


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

HEALTH WARNING: Care should be taken when lifting this product,
since its mass, and thus its weight, is dependent on its velocity
relative to the user.


Updated at: 2020-12-10 08:42 UTC