djf*_*djf 7 format common-lisp
Common Lisp支持过多的格式化指令.但是,我找不到一个方便的指示我的问题.基本上,我想打印一个数字网格.
使用列表,以下工作很好:
(format t "~{~A|~A|~A~%~^-----~%~}" '(1 2 3 4 5 6 7 8 9))
1|2|3
-----
4|5|6
-----
7|8|9
NIL
Run Code Online (Sandbox Code Playgroud)
我无法找到类似的构造来迭代向量.CLtL2明确指出 ~{...~}要将列表作为参数.无论如何我尝试使用矢量,但是我的Clisp正确地说出了错误的参数类型.作为一种解决方法,我使用全能将我的矢量转换为一个扔掉的列表loop.
(let ((lst (loop for e across '#(1 2 3 4 5 6 7 8 9) collecting e)))
(format t "~{~A|~A|~A~%~^-----~%~}" lst))
1|2|3
-----
4|5|6
-----
7|8|9
NIL
Run Code Online (Sandbox Code Playgroud)
这是有效的,但它让我感到笨拙的临时解决方案.我宁愿不为此创建大量的临时列表format.有没有办法直接迭代向量?
出于好奇,有没有理由format不支持序列?
小智 7
(defun pprint-array (stream array
&optional colon amp (delimiter #\Space))
(declare (ignore colon amp))
(loop
:with first-time = t
:for x :across array
:unless first-time :do (format stream "~C" delimiter) :end
:do (format stream "~S" x)
(setf first-time nil)))
(format t "~' :@/pprint-array/" #(1 2 3 4)) ; 1 2 3 4
Run Code Online (Sandbox Code Playgroud)
您可以添加更多参数(它们将以逗号分隔),或者您也可以以某种方式处理冒号和符号.
按照Svante的建议这里有一个稍微改变的函数版本,它也使用冒号和&符号通过以下方式:冒号使它在prin1和之间改变princ和at符号使它以递归方式打印嵌套数组(它可能更复杂,也可以打印多维数组等......但这里的时间有限,它是什么:
(defun pprint-array (stream array
&optional colon amp
(delimiter #\Space) (line #\Newline))
(if amp (loop
:with first-time = t
:for a :across array
:unless first-time
:do (when line (write-char line stream)) :end
:if (or (typep a 'array) (typep a 'vector))
:do (pprint-array stream a colon amp delimiter line)
:else
:do (if colon (prin1 a stream) (princ a stream)) :end
:do (setf first-time nil))
(loop
:with first-time = t
:for x :across array
:unless first-time
:do (when delimiter (write-char delimiter stream)) :end
:do (if colon (prin1 x stream) (princ x stream))
(setf first-time nil))))
Run Code Online (Sandbox Code Playgroud)