这个问题可能会以一个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)
也许我在这里想的太复杂了,有一种更简单的方法可以做我想要的事情,但我想我自己陷入了一个我无法摆脱的心理角落.
我认为你有两个选择:让format魔法去使用其他循环结构或生成格式字符串本身:
(defun facepalm-printer (lol)
(format t (format nil "~~{|~~{ ~~~ad~~}|~~%~~}"
(longest-member lol))
lol))
Run Code Online (Sandbox Code Playgroud)
定义longest-member留给读者作为练习.
假设所需的宽度绑定到width,那么您可以这样做:
(format t "~{|~{ ~Vd~}|~%~}" width '((1 23 2 312) (23 456 1 7890)))
Run Code Online (Sandbox Code Playgroud)
5已被替换V并width作为参数添加到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 ...)表达式实现了这一点。