CL格式化配方:将nil作为值处理

时间:2015-08-19 17:00:55

标签: format common-lisp

我一直在查看格式化食谱,而且我无法找到我正在寻找的东西......

(format nil CONTROL-STRING day name num-apples)

假设我不想更改上述表单中的参数,只需CONTROL-STRING

daynum-apples将始终为非零,但name可能为零。

name为零时,我希望输出看起来像

"Today is Monday. Hello, you have 3 apples."

但是当定义name时,我希望它看起来像

"Today is Monday. Hello Adam, you have 3 apples."

因此控制字符串需要查看name,在非零情况下使用它,而不是在nil情况下使用它,但在两种情况下都使用它。

也许可以通过消耗nil并将其打印为""来实现?如果是这样,我不知道该怎么做。

1 个答案:

答案 0 :(得分:10)

您链接到的问题Lisp format directive that interprets nil argument to empty string instead of "NIL"确实包含一个答案,说明如何执行此操作,但不引用任何文档。由于您正在生成英文文本,因此您还可以考虑其他一些选项。

首先,使用〜@ [结果〜] ,您可以在参数为非零的情况下处理结果格式指令,并且参数为〜@ [>未被消耗,因此它仍然可用。一般来说, 22.3.7.2 Tilde Left-Bracket: Conditional Expression描述了很多选项,但关于〜@ [它说:

  

〜@ [结果〜]测试参数。如果是真的那么论证   没有被〜[命令用尽但仍然是下一个命令   已处理,并处理了一个子句。如果arg是   false,然后参数用完,并且不处理该子句。   因此,该条款通常应该只使用一个参数,并且可以   期待它是非零的。

您可以按如下方式使用:

(defun test (day name n-apples)
  (format nil "Today is ~a. Hello~@[ ~a~], you have ~a apples."
          day name n-apples))

CL-USER> (test 'monday 'adam 2)
"Today is MONDAY. Hello ADAM, you have 2 apples."
CL-USER> (test 'tuesday nil 42)
"Today is TUESDAY. Hello, you have 42 apples."

为了使其更加强大,您应该考虑使用~p for pluralization,以便获得“1个苹果”和“3个苹果 s ”。

(defun test (day name n-apples)
  (format nil "Today is ~a. Hello~@[ ~a~], you have ~a apple~:P."
          day name n-apples))

CL-USER> (test 'monday 'john 2)
"Today is MONDAY. Hello JOHN, you have 2 apples."
CL-USER> (test 'tuesday 'john 1)
"Today is TUESDAY. Hello JOHN, you have 1 apple."
CL-USER> (test 'wednesday nil 0)
"Today is WEDNESDAY. Hello, you have 0 apples."

最后,由于您正在生成文本,因此您可能会感谢某些案例规范化(例如,使用首字母大写打印专有名词),并在文本中写入数字:

(defun test (day name n-apples)
  (format nil "Today is ~:(~a~). Hello~@[ ~:(~a~)~], you have ~r apple~:P."
          day name n-apples))
CL-USER> (list
          (test 'monday 'adam 4)
          (test 'tuesday 'john 1)
          (test 'wednesday 'mary\ sue 42)
          (test 'thursday 'jim-bob 0))
("Today is Monday. Hello Adam, you have four apples."
 "Today is Tuesday. Hello John, you have one apple."
 "Today is Wednesday. Hello Mary Sue, you have forty-two apples."
 "Today is Thursday. Hello Jim-Bob, you have zero apples.")