From: Len Charest
Subject: shadowing defstruct print-function
Date: 
Message-ID: <1991May31.183953.29579@jpl-devvax.jpl.nasa.gov>
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
*

From: Eric Benson
Subject: Re: shadowing defstruct print-function
Date: 
Message-ID: <EB.91May31142722@watergate.lucid.com>
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
From: Kevin Thompson
Subject: Re: shadowing defstruct print-function
Date: 
Message-ID: <13268@ptolemy-ri.arc.nasa.gov>
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
From: Barry Margolin
Subject: Re: shadowing defstruct print-function
Date: 
Message-ID: <1991Jun1.203541.23931@Think.COM>
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
From: Barry Margolin
Subject: Re: shadowing defstruct print-function
Date: 
Message-ID: <1991Jun1.202137.23293@Think.COM>
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