是否有一个格式指令来迭代Common Lisp中的向量?

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)