Format - Help with printing a table

This question will probably end in facepalm, but I tried for a while and still got stuck despite reading the hyperspec.

Basically, I want to do something like

(format t "~{|~{ ~5d~}|~%~}" '((1 23 2 312) (23 456 1 7890))) 

but instead of hardcoding 5 it should be computed from a list (the length of the longest element from any nested list is + 1) to give something like

 | 1 23 2 312| | 23 456 1 7890| 

Perhaps I am getting too complicated here, and there is an easier way to do what I want, but I think I launched myself into a psychic corner from which I cannot get out.

+6
format lisp
source share
2 answers

Assuming the required width is bound to width , you can do this:

 (format t "~{|~{ ~Vd~}|~%~}" width '((1 23 2 312) (23 456 1 7890))) 

5 was replaced with V , and width was added as an argument to FORMAT /

edit: original answer incorrectly entered nested directives

In the format control string, V can be used instead of any constant value, indicating that the corresponding value should be taken from the argument list.

You can try the following:

 (setf width 5) (setf data '((1 23 2 312) (23 456 1 7890))) (format t "~{|~{ ~{~Vd~}~}|~%~}" (mapcar #'(lambda (r) (mapcar #'(lambda (v) (list width v)) r)) data) ) 

This format string requires that the desired width be preceding each value. An expression (mapcar ...) does this.

+3
source share

I think you have two options: let the magic of the format go and use other loop constructs or generate the format itself:

 (defun facepalm-printer (lol) (format t (format nil "~~{|~~{ ~~~ad~~}|~~%~~}" (longest-member lol)) lol)) 

The definition of longest-member remains as an exercise for the reader.

+5
source share

All Articles