[racket] Behaviour of gen:custom-write method

From: Jens Axel Søgaard (jensaxel at soegaard.net)
Date: Sat May 17 15:09:22 EDT 2014

Hi Hamish,

I find this confusing too.

It seems that the pretty printer calls the different handlers in order
to detect cycles. If one turns of the pretty printer I get two calls
instead of one.
I am not exactly sure, why the pretty printer needs to this.

The code in question:

https://github.com/plt/racket/blob/0eb29a4dcf7c63e9e3881469deee2d655f2dd786/racket/collects/racket/pretty.rkt#L460

/Jens Axel



2014-05-17 20:44 GMT+02:00 Hamish Ivey-Law <hamish.ivey.law at gmail.com>:
> Dear Racket-users
>
> I am trying to understand the behaviour of the `gen:custom-write`
> method. What I find confusing is that the `write-proc` function is
> called twice for explicit calls to `write`, `display` or `print` and
> three times when display happens in the (x)repl.  For example:
>
> -> (struct thing (n)
>            #:methods gen:custom-write
>            [(define (write-proc tg port mode)
>               (printf "In thing write-proc (port = ~a, mode = ~a)~%" port mode)
>               (fprintf port "Thing is ~a~%" (thing-n tg)))])
> -> (define tg (thing 7))
> -> tg
> In thing write-proc (port = #<output-port:null>, mode = #f)
> In thing write-proc (port = #<output-port:null>, mode = #f)
> In thing write-proc (port = #<printing-port>, mode = 0)
> Thing is 7
>
> If the printing mode is specified explicitly by using `write`,
> `display` or `print`, then `write-proc` is still called twice:
>
> -> (write tg)
> In thing write-proc (port = #<output-port:null>, mode = #t)
> In thing write-proc (port = #<output-port:redirect>, mode = #t)
> Thing is 7
> -> (display tg)
> In thing write-proc (port = #<output-port:null>, mode = #f)
> In thing write-proc (port = #<output-port:redirect>, mode = #f)
> Thing is 7
> -> (print tg)
> In thing write-proc (port = #<output-port:null>, mode = #t)
> In thing write-proc (port = #<output-port:redirect>, mode = 0)
> Thing is 7
>
> Is there an example of an implementation of `write-proc` which shows
> how one should handle the combinations of values of `port` and `mode`
> (and whatever else) in such a way that, for example, we can avoid
> potentially expensive conversions to strings which are later
> discarded?  Or are we simply expected to cache anything that we don't
> want to recompute ourselves?  What is the rationale behind calling
> `write-proc` several times?  Where is this behaviour documented (other
> than in the Racket source, obviously)?
>
> (In my particular application, the analogue of `n` is gigantic *and*
> must undergo a costly conversion to a string via FFI before being
> printed to a file.  Not something I can afford to do twice!)
>
> I am very new to Racket.  Please keep that in mind when responding!
> Thanks very much in advance!
>
> Kind regards,
> Hamish.
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users



-- 
--
Jens Axel Søgaard


Posted on the users mailing list.