Next: , Previous: , Up: syslib structs safe   [Index]


12.14.1.4 Structs printer customisation

Vicare’s built–in Scheme objects writer can print structs just fine, handling cyclic references and shared objects:

(import (vicare))
(print-graph #t)
(set-port-buffer-mode! (current-output-port)
                       (buffer-mode none))

(define-struct duo (one two))

;; simple struct
(display (make-duo 1 2))
-| #[struct duo one=1 two=2]

;; struct with shared object
(let* ((A (make-duo 1 2))
       (B (make-duo A A)))
  (display B))
-| #[struct duo one=#0=#[struct duo one=1 two=2] two=#0#]

;; struct with cyclic reference to itself
(let ((A (make-duo 1 (void))))
  (set-duo-two! A A)
  (display A))
-| #0=#[struct duo one=1 two=#0#]

The Scheme objects writer is able to differentiate between display, write and pretty-print printing. When printing structs, the built–in writer makes no difference between printing with display and write; it does it differently when printing with pretty-print:

(import (vicare))
(print-graph #t)
(set-port-buffer-mode! (current-output-port)
                       (buffer-mode none))

(define-struct duo (one two))

;; simple struct
(pretty-print (make-duo 1 2))
-| (struct duo (one 1) (two 2))

;; struct with shared object
(let* ((A (make-duo 1 2))
       (B (make-duo A A)))
  (pretty-print B))
-| (struct duo (one #0=(struct duo (one 1) (two 2))) (two #0#))

;; struct with cyclic reference to itself
(let ((A (make-duo 1 (void))))
  (set-duo-two! A A)
  (pretty-print A))
-| #0=(struct duo (one 1) (two #0#))

Custom printers

Sometimes, we need to print a struct with a customised representation. For example keyword objects (see Keyword objects) are structs with a custom printer function:

(display #:ciao)        ⇒ #:ciao

For every struct type it is possible to set a custom printer function; it accepts 3 arguments: the struct to be printed; a textual output port into which to write a string representation of the struct in the style of display, write or pretty-print; a sub–printer function to be optionally used to print component objects. The sub–printer function accepts as single argument the object to print; it allows us to interface with the shared objects printer that handles shared and cyclic references.

As example, the following code defines a custom printer, making use of the parameter printer-printing-style to differentiate the style:

(import (vicare))
(print-graph #t)
(set-port-buffer-mode! (current-output-port)
                       (buffer-mode none))

(define-struct duo (one two))

(define (duo-printer stru port sub-printer)
  (case (printer-printing-style)
    ((display)
     (display "#{duo " port)
     (sub-printer (duo-one stru))
     (display " " port)
     (sub-printer (duo-two stru))
     (display "}" port))
    ((write)
     (display "(" port)
     ;;By using the sub-printer: we make this sexp shared too.
     (sub-printer '(struct-constructor
                      (struct-type-descriptor duo)))
     (display " " port)
     (sub-printer (duo-one stru))
     (display " " port)
     (sub-printer (duo-two stru))
     (display ")" port))
    ((pretty-print)
     (sub-printer `(struct duo
                           #:one ,(duo-one stru)
                           #:two ,(duo-two stru))))))

(set-struct-type-printer! (struct-type-descriptor duo)
                          duo-printer)

(define O
  (make-duo 1 2))

(display O)
-| #{duo 1 2}"

(write O)
-| ((struct-constructor (struct-type-descriptor duo)) 1 2)

(pretty-print O)
-| (struct duo #:one 1 #:two 2)

;; shared object, display
(let* ((A (make-duo 1 2))
       (B (make-duo A A)))
  (display B))
-| #{duo #0=#{duo 1 2} #0#}

;; shared object, write
(let* ((A (make-duo 1 2))
       (B (make-duo A A)))
  (write B))
-| (#0=(struct-constructor (struct-type-descriptor duo)) \
  #1=(#0# 1 2) #1#)
Function: set-struct-type-printer! std printer

Select the procedure printer as printer for structs of type std; if printer is #f, instances of type std make use of the built–in Scheme objects printer. Return the old printer function or #f if no printer function was set for this std.

Function: struct-type-printer std

Return #f or a function previously set as custom struct printer for instances of struct type std. When the return value is #f: instances of type std make use of the built–in Scheme objects printer.


Next: , Previous: , Up: syslib structs safe   [Index]