Lisp 列表打印

Luí*_*sus 5 lisp common-lisp

我在 lisp 格式功能方面遇到了一些麻烦。我有以下清单:

((X X X)(X X X X X X)(X X X X X X X X X)) 
Run Code Online (Sandbox Code Playgroud)

我需要按以下格式打印它:

X  X  X
XX XX XX
XXXXXXXXX
Run Code Online (Sandbox Code Playgroud)

关于如何实现这一目标的任何想法?format 函数有点令人困惑,HyperSpec 文档似乎对我没有任何帮助。谢谢。

Vse*_*kin 3

就像每个工具format都有其局限性一样,它不太适合此类问题。可能您可以使用纯格式获得的最好的结果,而无需借助~?or的黑魔法~/,您或任何其他人将来可能不会理解,以下代码是:

CL-USER> (format t "~{~{~A ~}~%~}"
                 '((X X X) (X X X X X X) (X X X X X X X X X)))
X X X 
X X X X X X 
X X X X X X X X X 
Run Code Online (Sandbox Code Playgroud)

如果您想获得复杂的输出结构,请尝试进行一些预处理。就像,如果列表的格式是硬编码的,您可以使用:

(format t "~{~{~6A~} ~%~}"
          (mapcar (lambda (l)
                    (loop :for i :from 0 :to (1- (length l)) :by (/ (length l) 3)
                          :collect (format nil "~{~A ~}"
                                           (subseq l i (+ i (/ (length l) 3))))))
                  '((X X X) (X X X X X X) (X X X X X X X X X))))
Run Code Online (Sandbox Code Playgroud)

这里我们首先将列表中的项目收集到每个列表中相同数量的组中,打印它们,这样就得到了 3 个具有相同元素数量的列表,然后可以通过 进行处理format

format您可以在 Peter Seibel 的优秀 Lisp 书籍的相应章节中找到更多信息: http://gigamonkeys.com/book/a-few-format-recipes.html

编辑

如果您有可变数量的列表,并且每个列表都比前一个大两倍,则还需要事先准备格式字符串:

CL-USER> (defun format-custom-list (list)
           (format t (format nil "~~{~~{~~~DA~~} ~~%~~}" (* 2 (length list)))
                   (mapcar (lambda (l)
                             (let* ((len (length l))
                                    (len/3 (/ len 3)))
                               (loop :for i :from 0 :to (1- len) :by len/3 
                                     :collect (format nil "~{~A ~}"
                                                      (subseq l i (+ i len/3))))))
                           list)))
CL-USER> (format-custom-list '((X X X) (X X X X X X) (X X X X X X X X X)
                               (X X X X X X X X X X X X)))
X       X       X        
X X     X X     X X      
X X X   X X X   X X X    
X X X X X X X X X X X X  
NIL
Run Code Online (Sandbox Code Playgroud)

(尾部nil是 的输出format,它不会打印到输出流t。如果您想从此函数中获取字符串,请使用nilasformat的输出流。)

  • 我相信你可以在 REPL 中尝试一下这段代码。这里的`NIL`不是打印的部分,只是返回值,所以不用担心。 (2认同)