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. ·······@ai-cyclops.jpl.nasa.gov
JPL Artificial Intelligence Group
*
In article <······················@jpl-devvax.jpl.nasa.gov> ·······@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))
··@lucid.com Eric Benson
415/329-8400 x5523 Lucid, Inc.
Telex 3791739 LUCID 707 Laurel Street
Fax 415/329-8480 Menlo Park, CA 94025
In article <················@watergate.lucid.com> ··@lucid.com (Eric Benson) writes:
>In article <······················@jpl-devvax.jpl.nasa.gov> ·······@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
--
········@ptolemy.arc.nasa.gov NASA-Ames Research Center, Moffett Field, CA
In article <·····@ptolemy-ri.arc.nasa.gov> ········@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.
······@think.com
{uunet,harvard}!think!barmar
In article <······················@jpl-devvax.jpl.nasa.gov> ·······@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.
······@think.com
{uunet,harvard}!think!barmar