format - 帮助打印表格

Mic*_*ohl 6 lisp format

这个问题可能会以一个facepalm结束,但我已经尝试了一段时间,尽管阅读了hyperspec,我仍然陷入困境.

基本上我想做的就是这样

(format t "~{|~{ ~5d~}|~%~}" '((1 23 2 312) (23 456 1 7890)))
Run Code Online (Sandbox Code Playgroud)

但不是硬编码5,而是应该从列表中计算出来(任何嵌套列表中最长元素的长度+ 1)来给出像

|    1    23     2   312|
|   23   456     1  7890|      
Run Code Online (Sandbox Code Playgroud)

也许我在这里想的太复杂了,有一种更简单的方法可以做我想要的事情,但我想我自己陷入了一个我无法摆脱的心理角落.

Sva*_*nte 5

我认为你有两个选择:让format魔法去使用其他循环结构或生成格式字符串本身:

(defun facepalm-printer (lol)
  (format t (format nil "~~{|~~{ ~~~ad~~}|~~%~~}"
                    (longest-member lol))
          lol))
Run Code Online (Sandbox Code Playgroud)

定义longest-member留给读者作为练习.


WRe*_*ach 4

假设所需的宽度绑定到width,那么您可以这样做:

(format t "~{|~{ ~Vd~}|~%~}" width '((1 23 2 312) (23 456 1 7890)))
Run Code Online (Sandbox Code Playgroud)

5已被替换Vwidth作为参数添加到FORMAT/

编辑:原始答案没有正确解释嵌套指令

在格式中,控制字符串V可以用来代替任何常量值,指示相应的值将从参数列表中获取。

你可以试试这个:

(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) )
Run Code Online (Sandbox Code Playgroud)

此格式字符串要求每个值前面都有所需的宽度。该(mapcar ...)表达式实现了这一点。