How do I format the digit precision of my REPL output in Lisp?
Asked Answered
C

1

6

My question is:
How can I set the precision of my REPL print output?

As an example, this simple function here:

(defun gaussian (rows cols sigma)
  (let ((filter (make-array `(,rows ,cols)))
    (rowOffset (/ (- rows 1) 2.0))
    (colOffset (/ (- cols 1) 2.0)))
    (loop for i from 0 to (- rows 1)
       do (loop for j from 0 to (- cols 1)
           do (setf (aref filter i j)
            (gaussDistVal i j rowOffset ColOffset sigma))))
    filter))

If I call (gaussian 5 5 1), my output is the following:

#2A((0.01831564 0.082085 0.13533528 0.082085 0.01831564)
    (0.082085 0.36787945 0.60653067 0.36787945 0.082085)
    (0.13533528 0.60653067 1.0 0.60653067 0.13533528)
    (0.082085 0.36787945 0.60653067 0.36787945 0.082085)
    (0.01831564 0.082085 0.13533528 0.082085 0.01831564))

Whereas I'd like to get:

#2A((0.0 0.1 0.1 0.1 0.0)
    (0.0 0.4 0.6 0.4 0.1)
    (0.1 0.6 1.0 0.6 0.1)
    (0.0 0.4 0.6 0.4 0.1)
    (0.0 0.1 0.1 0.1 0.0))

If you have the answer, could you also please tell me where these "REPL customisations" are documented?

(SBCL 1.2.11; Slime on Emacs 25)

Crompton answered 15/12, 2015 at 22:58 Comment(2)
Side note: your loops might be better expressed as dotimes: (dotimes (i rows) (dotimes (j cols) #| .... |#).Geary
And you can use (loop for i from 0 below rows... (and the from 0 is optional) instead of (loop for i from 0 to (- rows 1)... or (if you absolutely want to do arithmetic on your bounds) (1- rows).Junji
S
10

Using the Common Lisp pretty printer

Common Lisp has an extensive pretty printer. A rarely used feature is a dispatch table for controlling the printing of objects of a certain type. See set-pprint-dispatch how to configure this functionality.

The function format has features to output various forms of float numbers.

This example combines both:

CL-USER 32 > (set-pprint-dispatch 'float
                                  #'(lambda (s obj)
                                      (format s "~,1F" obj)))
NIL

CL-USER 33 > (setf *print-pretty* t)
T

CL-USER 34 > #2A((0.01831564 0.082085 0.13533528 0.082085 0.01831564)
                 (0.082085 0.36787945 0.60653067 0.36787945 0.082085)
                 (0.13533528 0.60653067 1.0 0.60653067 0.13533528)
                 (0.082085 0.36787945 0.60653067 0.36787945 0.082085)
                 (0.01831564 0.082085 0.13533528 0.082085 0.01831564))

#2A((0.0 0.1 0.1 0.1 0.0)
    (0.1 0.4 0.6 0.4 0.1)
    (0.1 0.6 1.0 0.6 0.1)
    (0.1 0.4 0.6 0.4 0.1)
    (0.0 0.1 0.1 0.1 0.0))

One may also want to use it temporarily:

CL-USER 37 > (let ((*print-pprint-dispatch* (copy-pprint-dispatch)))
               (set-pprint-dispatch 'float
                                    #'(lambda (s obj)
                                        (format s "~,1F" obj)))
               (pprint #2A((0.01831564 0.082085 0.13533528 0.082085 0.01831564)
                           (0.082085 0.36787945 0.60653067 0.36787945 0.082085)
                           (0.13533528 0.60653067 1.0 0.60653067 0.13533528)
                           (0.082085 0.36787945 0.60653067 0.36787945 0.082085)
                           (0.01831564 0.082085 0.13533528 0.082085 0.01831564))))

#2A((0.0 0.1 0.1 0.1 0.0)
    (0.1 0.4 0.6 0.4 0.1)
    (0.1 0.6 1.0 0.6 0.1)
    (0.1 0.4 0.6 0.4 0.1)
    (0.0 0.1 0.1 0.1 0.0))
Singultus answered 15/12, 2015 at 23:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.