Hi,
I did the following test:
(defstruct (z (:constructor make-z (x y))
(:print-function print-z))
x y)
(defun print-z (self sink depth)
(write-string (format nil "[~D/~D " depth *print-level*) sink)
(prin1 (z-x self) sink)
(princ " " sink)
(prin1 (z-y self) sink)
(princ "]" sink))
(defun test ()
(print (list (lisp-implementation-type)
(lisp-implementation-version)))
;; print-level test
(let ((*print-level* 2))
(print (make-z 'foo (make-z 'bar (make-z 'baz (make-z 'quux nil))))))
;; print-circle test
(let* ((*print-level* nil)
(*print-circle* t)
(last (make-z 'quux nil))
(z (make-z 'foo (make-z 'bar (make-z 'baz last)))))
(setf (z-y last) z)
(print z))
;; dont confuse the user
(values))
and get following results:
("CLISP" "1999-01-08 (January 1999)")
[1/2 FOO [2/2 BAR #]]
#1=[1/NIL FOO [2/NIL BAR [3/NIL BAZ [4/NIL QUUX #1#]]]]
("CMU Common Lisp"
"CMU Common Lisp 18a+ release x86-linux 2.4.5 29 June 1998 cvs libc5")
[0/2 FOO [0/2 BAR [0/2 BAZ [0/2 QUUX NIL]]]]
#1=[0/NIL FOO#2= [0/NIL BAR#2#[0/NIL BAZ#2#[0/NIL QUUX#2##1##3=]#3##3##3#
("Allegro CL Trial Edition" "5.0 [Linux/X86] (8/29/98 10:36)")
[0/2 FOO [0/2 BAR [0/2 BAZ [0/2 QUUX NIL]]]]
#2=[0/NIL FOO#1= [0/NIL BAR#1#[0/NIL BAZ#1#[0/NIL QUUX#1##2##3=]#3##3##3#
("LispWorks Personal Edition" "4.1.16 Beta")
[0/2 FOO [0/2 BAR [0/2 BAZ [0/2 QUUX NIL]]]]
#1=[0/NIL FOO #2=[0/NIL BAR #3=[0/NIL BAZ #4=[0/NIL QUUX #1#]]]]
("Kyoto Common Lisp" "GCL-2-2.2000000000000002")
[0/2 FOO [0/2 BAR [0/2 BAZ [0/2 QUUX NIL]]]]
#0=[0/NIL FOO #0=[0/NIL BAR #0= [... ad infinitum]
Error: Bind stack overflow.
However CLHS says under defstruct / :print-function:
| If the :print-function option is used, [...], the designated printer
| function is called on three arguments:
| - [...]
| - [...]
| - an integer indicating the current depth. The magnitude
| of this integer may vary between implementations;
| however, it can reliably be compared against
| *print-level* to determine whether depth abbreviation is
| appropriate.
This seems only be true for CLISP.
Further below it says:
| When *print-circle* is true, a user-defined print function
| can print objects to the supplied stream using write, prin1,
| princ, or format and expect circularities to be detected and
| printed using the #n# syntax.
This fails in GCL and is (human) readable in CLISP only.
So my question to the audience is: Why fail four of five implementations
the print-level test? Do they fail or is my reading of the CLHS a bit
too naive? Finally: What is the advertised way to implement portable
depth abbreviation in structure printers?
Gilbert.
--
;;; You know you have hacked Lisp too much, when you m-c-x in a C buffer.