charest@ai-cyclops.jpl.nasa.gov (Len Charest) (06/01/91)
Is it possible to shadow the print-function used to print a structure during a call to FORMAT? For example, suppose we have a structure FOO that prints using the print-function PRINT-FOO, i.e.,: (format t "~a" foo) => #<FOO> Now I want to locally redefine PRINT-FOO as in: (flet ((print-foo (foo stream depth) (declare (ignore foo depth)) (format stream "{Foo}"))) (format t "~a" foo)) => {Foo} execpt that FLET only has lexical scope and the ~a FORMAT directive calls PRINT-FOO at a nested level where the global definition is active. So #<FOO> will really be printed. Any pointers? -- * Len Charest, Jr. charest@ai-cyclops.jpl.nasa.gov JPL Artificial Intelligence Group *
eb@lucid.com (Eric Benson) (06/01/91)
In article <1991May31.183953.29579@jpl-devvax.jpl.nasa.gov> charest@ai-cyclops.jpl.nasa.gov (Len Charest) wrote: > Is it possible to shadow the print-function used to print a > structure during a call to FORMAT? For example, suppose we have a > structure FOO that prints using the print-function PRINT-FOO, i.e.,: > (format t "~a" foo) > => #<FOO> > Now I want to locally redefine PRINT-FOO as in: > (flet ((print-foo (foo stream depth) > (declare (ignore foo depth)) > (format stream "{Foo}"))) > (format t "~a" foo)) > => {Foo} > execpt that FLET only has lexical scope and the ~a FORMAT directive > calls PRINT-FOO at a nested level where the global definition is > active. So #<FOO> will really be printed. Any pointers? The simplest way to do this is: (defstruct (foo (:print-function print-foo)) <etc>) (defvar *print-foo-hook* #'(lambda (foo stream depth) <print foo the normal way>)) (defun print-foo (foo stream hook) (funcall *print-foo-hook* foo stream hook)) Then your local redefinition is: (let ((*print-foo-hook* #'(lambda (foo stream depth) (declare (ignore foo depth)) (format stream "{Foo}")))) (format t "~a" foo)) eb@lucid.com Eric Benson 415/329-8400 x5523 Lucid, Inc. Telex 3791739 LUCID 707 Laurel Street Fax 415/329-8480 Menlo Park, CA 94025
kthompso@ptolemy.arc.nasa.gov (Kevin Thompson) (06/01/91)
In article <EB.91May31142722@watergate.lucid.com> eb@lucid.com (Eric Benson) writes: >In article <1991May31.183953.29579@jpl-devvax.jpl.nasa.gov> charest@ai-cyclops.jpl.nasa.gov (Len Charest) wrote: >> Is it possible to shadow the print-function used to print a >> structure during a call to FORMAT? For example, suppose we have a >> structure FOO that prints using the print-function PRINT-FOO, i.e.,: >> (format t "~a" foo) >> => #<FOO> >(defstruct (foo (:print-function print-foo)) > <etc>) > >(defvar *print-foo-hook* > #'(lambda (foo stream depth) > <print foo the normal way>)) > >(defun print-foo (foo stream hook) > (funcall *print-foo-hook* foo stream hook)) > >Then your local redefinition is: > >(let ((*print-foo-hook* > #'(lambda (foo stream depth) > (declare (ignore foo depth)) > (format stream "{Foo}")))) > (format t "~a" foo)) Well this sounds great, and would be. But is there an implementation-independent way (or even implementation-dependent :) to "<print foo the normal way>"? I poked around at great length in both Franz & Lucid's system packages, and didn't find in either case something like "generic-defstruct-printer", which took any struct and printed it out with the #S (?) format. Does such a beast exist? It must in some ways, but I don't know that it's accessible to the user. -- Kevin Thompson -- kthompso@ptolemy.arc.nasa.gov NASA-Ames Research Center, Moffett Field, CA
barmar@think.com (Barry Margolin) (06/02/91)
In article <1991May31.183953.29579@jpl-devvax.jpl.nasa.gov> charest@AI-Cyclops.JPL.NASA.GOV writes: >Is it possible to shadow the print-function used to print a structure >during a call to FORMAT? Eric's suggestion with the *PRINT-FOO-HOOK* variable isn't bad. Here's what I thought of: (flet ((temp-print-foo ...)) (let ((real-print-foo (symbol-function 'print-foo))) (unwind-protect (progn (setf (symbol-function 'print-foo) #'temp-print-foo) ...) (setf (symbol-function 'print-foo) real-print-foo)))) Symbolics has a LETF macro that makes this kind of thing much easier to write. It's like LET, except the variable bindings can be SETF places. In that case, one could write: (letf (((symbol-function 'print-foo) #'(lambda ...))) ...) -- Barry Margolin, Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
barmar@think.com (Barry Margolin) (06/02/91)
In article <13268@ptolemy-ri.arc.nasa.gov> kthompso@ptolemy.arc.nasa.gov (Kevin Thompson) writes: >Well this sounds great, and would be. For what the original poster requested, it *is* great. > But is there an >implementation-independent way (or even implementation-dependent :) to >"<print foo the normal way>"? No, there's no portable way to print a structure the normal way, except by writing a structure-specific function that has the structure slot names hard-coded into it, e.g. (defun print-foo (object stream depth) (if (< depth *print-level*) (format stream "#S(~S :A ~S :B ~S)" 'foo (foo-a object) (foo-b object)) (write-char #\# stream))) There isn't necessarily even an implementation-dependent way; an implementation might define the above style of function as part of the DEFSTRUCT expansion. Since many implementations provide a way to discard structure slot information at run time, a generic structure printer may not be feasible. -- Barry Margolin, Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar