【问题标题】:Format over list: use arguments that aren't in list格式化列表:使用不在列表中的参数
【发布时间】:2016-03-22 17:58:00
【问题描述】:

这是我写的代码sn-p,但不起作用:

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

输出应如下所示:

Just|
do|
it|
!|

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

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

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

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

【问题讨论】:

  • 这几乎可以通过stackoverflow.com/q/8830888/1281433 的接受答案来回答,除了您不希望将分隔符编码到字符串中。 non-accepted answer 更通用,可以在这里使用(调整为让分隔符成为字符串,而不仅仅是字符)。
  • 这绝对是没有回答!我想在其他地方定义分隔符,整个问题就是关于这个 - 您展示的问题中的答案显示了如何使分隔符分隔元素而不是在每个元素之后打印。
  • 我说它几乎得到了回答。如果您不需要在外部定义分隔符,则只需:(format t "~{~A|~%~}" items)
  • @JoshuaTaylor 我不需要它来分开,而是在每个元素的末尾,除此之外我已经知道如何做你展示的 - 我错过的确切的东西是不在那里,所以答案对我来说没有多大用处,但感谢链接 - 有人可能会偶然发现它并发现它很有用。
  • 还是分隔符;你只是不要在最后一个元素之后省略它。在您的代码中,您甚至将其称为 separator

标签: format common-lisp


【解决方案1】:

稍微改变一下 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))

【讨论】:

    【解决方案2】:

    您可以使用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> 
    

    【讨论】:

    • 两个答案都有其缺点,但我想我更喜欢这个。
    【解决方案3】:

    这是一个黑客:

    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
    

    【讨论】:

    • 但是如果分隔符包含任何格式指令,这将不起作用。例如,如果分隔符是"~}""~A",您将不会得到正确的输出。
    • @JoshuaTaylor:是的。这是一个黑客。 ;-) 但它应该可以通过用另一个波浪号转义每个波浪号来修复。
    • 很好,这是一种方法。我希望有人会遇到更好的东西:)
    • 摆脱波浪号,完成。好吧,可以用另一种格式来完成。 ;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-27
    • 1970-01-01
    • 2018-05-08
    相关资源
    最近更新 更多