[racket] print/pretty-print weirdness

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Nov 11 17:39:05 EST 2013

Sorry for the long delay! And thanks for the smaller example, which is
helpful.


The problem is that the `write-proc` is called multiple times for a
single print, and the printer tries to keep track of quoting modes
across calls based on `eq?` identity.

If you change your example to have

  (define a-printable2-list (list {test-printable2}))

and use that for the recursive print in `write-proc` of
`test-printable`, then the output is as you expect.

The printer's dependency on `eq?` identity is not properly documented,
and my current thought is that the printer should be fixed, instead of
the documentation. For now, I hope knowing that `eq?` identity is
relevant will help you find a workaround.


Meanwhile, the explanation for

 > (print 'hello (current-output-port) 1)
 'hello

in DrRacket is that something is broken, because the right behavior is

 > (print 'hello (current-output-port) 1)
 hello

I'll look into that, too.


At Mon, 11 Nov 2013 12:29:36 -0700, Christopher wrote:
> Greetings again.
> 
> I'm still hoping for some help from you friendly bunch of geniuses!
> 
> Lest you think that the printing weirdness I described in my previous email is 
> relegated to that world of Racket OOP classes and objects, please look at this 
> example which uses only struct values:
> 
> 	#lang racket
> 	
> 	(struct test-printable []
> 	  #:property prop:custom-print-quotable 'never
> 	  #:methods gen:custom-write
> 	  [(define [write-proc strct port mode]
> 	     (when {eqv? mode 1}
> 	       {error "test-printable printed with depth of 1"} )
> 	     {fprintf port "(test-printable ~v)" {list {test-printable2}}} )])
> 	
> 	(struct test-printable2 []
> 	  #:property prop:custom-print-quotable 'never
> 	  #:methods gen:custom-write
> 	  [(define [write-proc strct port mode]
> 	     (when {eqv? mode 1}
> 	       {error "test-printable2 printed with depth of 1"} )
> 	     {display "(test-printable2)" port} )])
> 
> Here is an interactions session:
> 
> 	> {test-printable2} 
> 	(test-printable2) 
> 
> 	> {list {test-printable2}} 
> 	(list (test-printable2)) 
> 
> 	> {test-printable} ; produces error
> 	 . . test-printable2 printed with depth of 1
> 
> 
> What I want is for the third expression line to print the below:
> 
> 	(test-printable (list (test-printable2)))
> 
> But as you can see, that is not what happens. I don't understand why it does 
> what it's doing. Furthermore, is there a solution can I use to get print to 
> write stuff out without forcing it to be quoted when it isn't supposed to be?
> 
> By the way, if I change the above code so that print is explicitly at quote 
> depth of 0, print ignores it and calls the write-proc handler with quote depth 
> of 1 anyway, thus giving the same error:
> 
> 	(struct test-printable []
> 	  #:property prop:custom-print-quotable 'never
> 	  #:methods gen:custom-write
> 	  [(define [write-proc strct port mode]
> 	     (when {eqv? mode 1}
> 	       {error "test-printable printed with depth of 1"} )
> 	     {display "(test-printable " port}
> 	     {print {list {test-printable2}} port 0} ; explicitly at quote 
> depth of 0 but is IGNORED!
> 	     {display ")" port} )])
> 
> 	> {test-printable} ; still produces error
> 	 . . test-printable2 printed with depth of 1
> 
> I would love you hear back from someone in the know. Many thanks!
> 
> --Christopher
> 
> 
> 
> On Nov 5, 2013, at 12:09 PM, Christopher <ultimatemacfanatic at gmail.com> wrote:
> 
> > I'm experiencing some weirdness with print and pretty-print.
> > 
> > First of all, can someone please explain why these print the same thing:
> > 
> > > (print 'hello (current-output-port) 0)
> > 'hello
> > > (print 'hello (current-output-port) 1)
> > 'hello
> > 
> > But these do not:
> > 
> > > (pretty-print 'hello (current-output-port) 0)
> > 'hello
> > > (pretty-print 'hello (current-output-port) 1)
> > hello
> > 
> > (notice the bottom line has no quote in front of the symbol)
> > 
> > It seems to me that (print 'hello (current-output-port) 1) should not print 
> with a single-quote in front of the symbol, but it does, as you can see above.
> > 
> > 
> > Consider this:
> > 
> > #lang racket
> > 
> > (define allow-quoted #t)
> > 
> > (define printable-unquoted<%>
> >   (interface* []
> >     [[prop:custom-print-quotable 'never]
> >      [prop:custom-write 
> >        (lambda (obj port mode)
> >          (cond
> >            [{eq? mode #t} (send obj custom-write port)]
> >            [{eq? mode #f} (send obj custom-display port)]
> >            [(or {= mode 0} allow-quoted) (send obj custom-print port)]
> >            [{= mode 1} {error {string-append "printable-unquoted<%> object "
> >                                       "called with depth of 1" }}]))]]
> >      custom-write custom-display custom-print ))
> > 
> > (define test-printable%
> >   (class* object% [printable-unquoted<%>]
> >     (super-make-object)
> >     
> >     (define/public [custom-print port]
> >       {display "(make-object test-printable%)" port} )
> >     
> >     (define/public [custom-write port]
> >       {display "|;-)" port} )
> >     
> >     (define/public [custom-display port]
> >       {custom-write port} ))) 
> > 
> > (struct test-printable []
> >   #:property prop:custom-print-quotable 'never
> >   #:methods gen:custom-write
> >   [(define [write-proc strct port arg]
> >      {fprintf port "(test-printable ~v)" {vector (new test-printable%)}} )])
> > 
> > 
> > {print {test-printable}}
> > 
> > If I run it with (define allow-quoted #t) then the result is:
> > 
> > (test-printable '#((make-object test-printable%)))
> > 
> > Notice that the declared unquotable object is printed in the middle of a 
> quoted vector!!
> > 
> > If I set allow-quoted to #f then we confirm the obvious:
> > 
> > (test-printable '#(. . printable-unquoted<%> object called with depth of 1
> > 
> > Can anyone tell me why my prop:custom-print-quotable 'never is not being 
> respected on my class instance?
> > 
> > Thanks,
> > 
> > Christopher
> 
> 
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users

Posted on the users mailing list.