CLHS WRITE doesn't say much about how lisp objects are printed...
In particular, it doesn't specifies explicitely how PRINT-OBJECT should be used.
CLHS PRINT-OBJECT says that it's "called by the Lisp printer" (and
even precise that it shouldn't be called by the user, but nothing more).
So, with a careless reading, one could expect that defining a
PRINT-OBJECT EQL method on a lisp object whatever it's type, would be
enough to have WRITE (and the PRIN1, PRINC, and PRINT functions that
should call WRITE) call PRINT-OBJECT to print it, or in general, that
defining a PRINT-OBJECT method specialized on the class of any object
would be enough.
But PRINT-OBJECT specifies as ("valid", I guess) method signatures
only STANDARD-OBJECT or STRUCTURE-OBJECT for its first argument. In
consequence, it's implementation dependant whether PRINT-OBJECT is
called on objects that are neither STANDARD-OBJECT or STRUCTURE-OBJECT,
including any object of a builtin class, like FUNCTION.
This is surprizing, given "22.1.3 Default Print-Object Methods", but
"11.1.2.1.2 Constraints on the COMMON-LISP Package for Conforming
Programs" actually specifies undefined consequences when overriding
PRINT-OBJECT for any _standardized_ class like FUNCTION (point 19).
Therefore we cannot use PRINT-OBJECT to define any fancy output for
random lisp objects, only for our own user defined (standard and
structure) classes.
I would have liked to get the behavior of ACL as standard behavior :-(
% clall '(setf *print-readably* nil)'\
'(defvar *f* (lambda (x) x))'\
'(defmethod print-object ((self (eql *f*)) stream)
(format stream "#<An identity function>") self)'\
'(progn (princ *f*) (print *f*))'
========================================================================
CLISP 2.39 (2006-07-16) (built 3364813332) (memory 3364813914)
Evaluation of
(SETF *PRINT-READABLY* NIL)
produced nothing on *STANDARD-OUTPUT*
produced nothing on *ERROR-OUTPUT*
produced the following values:
--> NIL
Evaluation of
(DEFVAR *F* (LAMBDA (X) X))
produced nothing on *STANDARD-OUTPUT*
produced nothing on *ERROR-OUTPUT*
produced the following values:
--> *F*
Evaluation of
(DEFMETHOD PRINT-OBJECT ((SELF (EQL *F*)) STREAM)
(FORMAT STREAM "#<An identity function>") SELF)
produced nothing on *STANDARD-OUTPUT*
produced nothing on *ERROR-OUTPUT*
produced the following values:
--> #<STANDARD-METHOD ((EQL #<FUNCTION :LAMBDA (X) X>) #<BUILT-IN-CLASS T>)>
Evaluation of
(PROGN (PRINC *F*) (PRINT *F*))
produced the following *STANDARD-OUTPUT* (lines excluded):
------------------------------------------------------------------------
#<FUNCTION LAMBDA (X) X>
#<FUNCTION :LAMBDA (X) X>
------------------------------------------------------------------------
produced nothing on *ERROR-OUTPUT*
produced the following values:
--> #<FUNCTION :LAMBDA (X) X>
========================================================================
[... other implementations are similar to clisp ...]
========================================================================
International Allegro CL Free Express Edition 8.0 [Linux (x86)] (Jun 6, 2006 16:01)
Evaluation of
(SETF *PRINT-READABLY* NIL)
produced nothing on *STANDARD-OUTPUT*
produced nothing on *ERROR-OUTPUT*
produced the following values:
--> NIL
Evaluation of
(DEFVAR *F* (LAMBDA (X) X))
produced nothing on *STANDARD-OUTPUT*
produced nothing on *ERROR-OUTPUT*
produced the following values:
--> *F*
Evaluation of
(DEFMETHOD PRINT-OBJECT ((SELF (EQL *F*)) STREAM) (FORMAT STREAM "#<An identity function>") SELF)
produced nothing on *STANDARD-OUTPUT*
produced nothing on *ERROR-OUTPUT*
produced the following values:
--> #<STANDARD-METHOD PRINT-OBJECT ((EQL #<Interpreted Closure (unnamed) @ #x716de3d2>) T)>
Evaluation of
(PROGN (PRINC *F*) (PRINT *F*))
produced the following *STANDARD-OUTPUT* (lines excluded):
------------------------------------------------------------------------
#<An identity function>
#<An identity function>
------------------------------------------------------------------------
produced nothing on *ERROR-OUTPUT*
produced the following values:
--> #<An identity function>
========================================================================
--
__Pascal Bourguignon__ http://www.informatimago.com/
"Logiciels libres : nourris au code source sans farine animale."
Pascal Bourguignon wrote:
> CLHS WRITE doesn't say much about how lisp objects are printed...
> In particular, it doesn't specifies explicitely how PRINT-OBJECT should be used.
>
> CLHS PRINT-OBJECT says that it's "called by the Lisp printer" (and
> even precise that it shouldn't be called by the user, but nothing more).
This is the kind of situation a CDR could be useful for.
It is not obvious, but printing is directed by the
pprint-dispatch-table and not method specialization. The only time it
uses print-object is when there is no entry in that table.
See
http://www.lispworks.com/documentation/HyperSpec/Body/22_bad.htm
Arthur
Pascal Bourguignon wrote:
> CLHS WRITE doesn't say much about how lisp objects are printed...
> In particular, it doesn't specifies explicitely how PRINT-OBJECT should be used.
>
> CLHS PRINT-OBJECT says that it's "called by the Lisp printer" (and
> even precise that it shouldn't be called by the user, but nothing more).
>
>
> So, with a careless reading, one could expect that defining a
> PRINT-OBJECT EQL method on a lisp object whatever it's type, would be
> enough to have WRITE (and the PRIN1, PRINC, and PRINT functions that
> should call WRITE) call PRINT-OBJECT to print it, or in general, that
> defining a PRINT-OBJECT method specialized on the class of any object
> would be enough.
>
> But PRINT-OBJECT specifies as ("valid", I guess) method signatures
> only STANDARD-OBJECT or STRUCTURE-OBJECT for its first argument. In
> consequence, it's implementation dependant whether PRINT-OBJECT is
> called on objects that are neither STANDARD-OBJECT or STRUCTURE-OBJECT,
> including any object of a builtin class, like FUNCTION.
>
> This is surprizing, given "22.1.3 Default Print-Object Methods", but
> "11.1.2.1.2 Constraints on the COMMON-LISP Package for Conforming
> Programs" actually specifies undefined consequences when overriding
> PRINT-OBJECT for any _standardized_ class like FUNCTION (point 19).
>
>
>
> Therefore we cannot use PRINT-OBJECT to define any fancy output for
> random lisp objects, only for our own user defined (standard and
> structure) classes.
>
>
> I would have liked to get the behavior of ACL as standard behavior :-(
>
>
>
> % clall '(setf *print-readably* nil)'\
> '(defvar *f* (lambda (x) x))'\
> '(defmethod print-object ((self (eql *f*)) stream)
> (format stream "#<An identity function>") self)'\
> '(progn (princ *f*) (print *f*))'
> ========================================================================
> CLISP 2.39 (2006-07-16) (built 3364813332) (memory 3364813914)
>
>
> Evaluation of
> (SETF *PRINT-READABLY* NIL)
> produced nothing on *STANDARD-OUTPUT*
> produced nothing on *ERROR-OUTPUT*
> produced the following values:
> --> NIL
>
>
> Evaluation of
> (DEFVAR *F* (LAMBDA (X) X))
> produced nothing on *STANDARD-OUTPUT*
> produced nothing on *ERROR-OUTPUT*
> produced the following values:
> --> *F*
>
>
> Evaluation of
> (DEFMETHOD PRINT-OBJECT ((SELF (EQL *F*)) STREAM)
> (FORMAT STREAM "#<An identity function>") SELF)
> produced nothing on *STANDARD-OUTPUT*
> produced nothing on *ERROR-OUTPUT*
> produced the following values:
> --> #<STANDARD-METHOD ((EQL #<FUNCTION :LAMBDA (X) X>) #<BUILT-IN-CLASS T>)>
>
>
> Evaluation of
> (PROGN (PRINC *F*) (PRINT *F*))
> produced the following *STANDARD-OUTPUT* (lines excluded):
> ------------------------------------------------------------------------
> #<FUNCTION LAMBDA (X) X>
> #<FUNCTION :LAMBDA (X) X>
> ------------------------------------------------------------------------
> produced nothing on *ERROR-OUTPUT*
> produced the following values:
> --> #<FUNCTION :LAMBDA (X) X>
>
> ========================================================================
> [... other implementations are similar to clisp ...]
> ========================================================================
> International Allegro CL Free Express Edition 8.0 [Linux (x86)] (Jun 6, 2006 16:01)
>
>
> Evaluation of
> (SETF *PRINT-READABLY* NIL)
> produced nothing on *STANDARD-OUTPUT*
> produced nothing on *ERROR-OUTPUT*
> produced the following values:
> --> NIL
>
>
> Evaluation of
> (DEFVAR *F* (LAMBDA (X) X))
> produced nothing on *STANDARD-OUTPUT*
> produced nothing on *ERROR-OUTPUT*
> produced the following values:
> --> *F*
>
>
> Evaluation of
> (DEFMETHOD PRINT-OBJECT ((SELF (EQL *F*)) STREAM) (FORMAT STREAM "#<An identity function>") SELF)
> produced nothing on *STANDARD-OUTPUT*
> produced nothing on *ERROR-OUTPUT*
> produced the following values:
> --> #<STANDARD-METHOD PRINT-OBJECT ((EQL #<Interpreted Closure (unnamed) @ #x716de3d2>) T)>
>
>
> Evaluation of
> (PROGN (PRINC *F*) (PRINT *F*))
> produced the following *STANDARD-OUTPUT* (lines excluded):
> ------------------------------------------------------------------------
> #<An identity function>
> #<An identity function>
> ------------------------------------------------------------------------
> produced nothing on *ERROR-OUTPUT*
> produced the following values:
> --> #<An identity function>
>
> ========================================================================
>
> --
> __Pascal Bourguignon__ http://www.informatimago.com/
>
> "Logiciels libres : nourris au code source sans farine animale."
"Arthur Smyles" <········@earthlink.net> writes:
> It is not obvious, but printing is directed by the
> pprint-dispatch-table and not method specialization. The only time it
> uses print-object is when there is no entry in that table.
>
> See
> http://www.lispworks.com/documentation/HyperSpec/Body/22_bad.htm
Even adding (setf *print-pretty* nil), I get the same results in all
the tested implementations.
But I'll have to study CL pretty-printing...
--
__Pascal Bourguignon__ http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay
From: Pascal Costanza
Subject: Re: What is not written in CLHS about WRITE and PRINT-OBJECT
Date:
Message-ID: <4rgv40Fr1kisU1@mid.individual.net>
Pascal Bourguignon wrote:
> CLHS WRITE doesn't say much about how lisp objects are printed...
> In particular, it doesn't specifies explicitely how PRINT-OBJECT should be used.
>
> CLHS PRINT-OBJECT says that it's "called by the Lisp printer" (and
> even precise that it shouldn't be called by the user, but nothing more).
There is a mention of pretty printing taking precedence over
print-object in 22.2.1.4 in the HyperSpec. Specifically, the default
value of *pretty-print* is implementation dependent, which means that it
is not clear whether print-object is used by default or not (IIUC). Play
around with *print-pretty* and *print-pprint-disptach* and see what happens.
> So, with a careless reading, one could expect that defining a
> PRINT-OBJECT EQL method on a lisp object whatever it's type, would be
> enough to have WRITE (and the PRIN1, PRINC, and PRINT functions that
> should call WRITE) call PRINT-OBJECT to print it, or in general, that
> defining a PRINT-OBJECT method specialized on the class of any object
> would be enough.
>
> But PRINT-OBJECT specifies as ("valid", I guess) method signatures
> only STANDARD-OBJECT or STRUCTURE-OBJECT for its first argument. In
> consequence, it's implementation dependant whether PRINT-OBJECT is
> called on objects that are neither STANDARD-OBJECT or STRUCTURE-OBJECT,
> including any object of a builtin class, like FUNCTION.
No, that's not what it means. It only means that there are two
predefined methods for standard-object and structure-object. This is
useful information when you want to define your own methods.
Specifically, it means that you can perform supercalls in methods on
structs and classes.
> This is surprizing, given "22.1.3 Default Print-Object Methods", but
> "11.1.2.1.2 Constraints on the COMMON-LISP Package for Conforming
> Programs" actually specifies undefined consequences when overriding
> PRINT-OBJECT for any _standardized_ class like FUNCTION (point 19).
>
> Therefore we cannot use PRINT-OBJECT to define any fancy output for
> random lisp objects, only for our own user defined (standard and
> structure) classes.
Yes, this restriction is defined because otherwise it's not clear what
happens when two different, possibly third-party libraries define
methods for the same predefined classes or instances thereof. I think
the rule for eql specializers is somewhat too strict, but there you go.
If you need user-defined methods on functions and have the CLOS MOP
available, you can of course define a subclass of
standard-generic-function just for this purpose.
> I would have liked to get the behavior of ACL as standard behavior :-(
I think toggling *pretty-print* should help (but I'm not 100% sure).
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/