我一直在查看格式化食谱,而且我无法找到我正在寻找的东西......
(format nil CONTROL-STRING day name num-apples)
假设我不想更改上述表单中的参数,只需CONTROL-STRING
。
day
和num-apples
将始终为非零,但name
可能为零。
当name
为零时,我希望输出看起来像
"Today is Monday. Hello, you have 3 apples."
但是当定义name
时,我希望它看起来像
"Today is Monday. Hello Adam, you have 3 apples."
因此控制字符串需要查看name
,在非零情况下使用它,而不是在nil情况下使用它,但在两种情况下都使用它。
也许可以通过消耗nil并将其打印为""
来实现?如果是这样,我不知道该怎么做。
答案 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.")