列表上的格式:使用不在列表中的参数

Format over list: use arguments that aren't in list

这是我写的一个代码片段,但不起作用:

(let ((separator "|")
      (text '("Just" "do" "it" "!")))
  (format t "~{~A~A~%~}" text separator))

输出应如下所示:

Just|
do|
it|
!|

但是,它不会那样工作 - 当我在 ~{~} 中时,我不知道如何从列表外部添加元素。我可以这样做:

(format t "~{~A|~%~}" text)

但这不允许我使用变量中的 separator,这就是我所追求的。

现在我知道我可以通过在每个偶数位置添加分隔符来合并 text 和分隔符,但这对我来说很难看。在 format 中还有其他方法吗?

这是一个技巧:

CL-USER 49 > (let ((separator "|")
                   (text '("Just" "do" "it" "!")))
                (format t
                        (concatenate 'string "~{~A" separator "~%~}")
                        text))
Just|
do|
it|
!|

在分隔符字符串中转义波浪号:

CL-USER 56 > (flet ((fix-tilde (string)
                      (with-output-to-string (s)
                        (loop for c across string
                              when (char= c #\~)
                              do (write-string "~~" s)
                              else do (write-char c s)))))
               (let ((separator (fix-tilde "~a~a"))
                     (text '("Just" "do" "it" "!")))
                 (format t
                         (concatenate 'string "~{~A" separator "~%~}")
                         text)))
Just~a~a
do~a~a
it~a~a
!~a~a

您可以使用 Tilde Slash 格式指令,它允许将用户定义的函数用作格式说明符。这只是给你一个可能的例子,很多变化都是可能的:

CL-USER> (defvar *separator* " ")
*SEPARATOR*
CL-USER> (defun q(stream arg &rest args)
           (declare (ignore args))
           (format stream "~a~a" arg *separator*))
Q
CL-USER> (let ((*separator* "|")
               (text '("Just" "do" "it" "!")))
           (format t "~{~/q/~%~}" text))
Just|
do|
it|
!|
NIL
CL-USER> (let ((*separator* "+++")
               (text '("Just" "do" "it" "!")))
           (format t "~{~/q/~%~}" text))
Just+++
do+++
it+++
!+++
NIL
CL-USER> 

稍微更改一下 renzo 的回答:如果我们使用 SPECIAL 声明,则不需要全局变量:

(defun %d1 (stream arg &rest args)
  (declare (ignore args)
           (special delim))
  (princ arg stream)
  (princ delim stream))

(defun my-print (list delim)
  (declare (special delim))
  (format nil "~{~/%d1/~%~}" list))