CL格式配方:处理nil作为值 [英] CL Format recipe: Dealing with nil as a value

查看:157
本文介绍了CL格式配方:处理nil作为值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(())(

格式nil CONTROL-STRING日期​​名称num-apples)



假设我不想改变上述形式的参数, code> CONTROL-STRING 。



天和 num-apples 总是非零,但是 name 可能是零。



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



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



今天是星期一,你好亚当,你有3个苹果。

所以控制字符串需要看 name ,在非零的情况下使用它,而不是使用它在零的情况下,但消费在这两种情况下。

也许它可以通过消费零和打印为 ?如果是的话,我不知道该怎么做。

你链接到 LISP格式指令,将nil参数解释为空字符串,而不是NIL,包括一个答案,显示如何做到这一点,但没有引用任何文档。由于您正在生成英文文本,因此还有其他一些选项可供您考虑。

首先,使用〜@ [consequent〜] ,可以处理后缀格式指令该参数是非零的,并且〜@ [的参数不被消耗,所以它仍然可用。一般情况下,
22.3.7.2左括号:条件表达式 描述了大量的选项,但是关于〜@ [):
$ b


〜@ [consequent〜 ]测试论证。如果它是真的,那么参数
没有被〜[命令用完,而是作为下一个被
处理的,并且处理了一个子句的结果。如果arg是
false,那么参数用完,并且不处理该子句。
因此,子句通常只使用一个参数,而
可能是非零的。 >你可以这样使用它:
$ b $ pre $ (defun test(day name n-apples)
(format nil今天是〜a。你好〜@〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

  CL-USER> (测试星期一亚当2)
今天是星期一。你好ADAM,你有2个苹果。
CL-USER> (测试'星期二零42)
今天是星期二,你好,你有42个苹果。

为了使其更加健壮,您应该考虑使用〜p for pluralization ,这样你就可以得到1苹果和3苹果 s >


$ b $ pre $ (defun test(day name n-apples)
(format nilToday is〜a。你好〜@ [〜a〜],你有〜一个苹果〜:P。
天名n-apples))

  CL-USER> (测试'星期一'约翰2)
今天是星期一,你好,约翰,你有2个苹果。
CL-USER> (测试'星期二'约翰1)
今天是星期二,你好,约翰,你有一个苹果。
CL-USER> (测试'星期三无0)
今天是星期三,你好,你有0个苹果。

最后,由于您正在生成文本,因此您可能会意识到某些情况下的规范化(例如,打印专有名词首字母大写),然后用文字写出数字:

 (defun test(day name n-apples)
(格式nil今天是〜:(〜a〜)。你好〜@ [〜:(〜a〜)〜],你有〜r苹果〜:P。
天名n-apples))





  CL-USER> (测试'星期三'亚当4)
(测试'星期二'约翰1)
(测试'星期三'玛丽\起诉42)
(测试'星期四' jim-bob 0))
(今天是星期一,你好,亚当,你有四个苹果)
今天是星期二,你好John,你有一个苹果。星期三,你好,玛丽苏,你有四十二个苹果。
今天是星期四,你好,吉姆 - 鲍勃,你有零苹果。)


I've been looking through formatting recipes , and I can't quite find what I'm looking for...

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

Suppose I don't want to change the arguments in the above form, just CONTROL-STRING.

day and num-apples will always be non-nil, but name might be nil.

When name is nil, I want the output to look like

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

but when name is defined, I want it to look like

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

So the control string needs to look at name, use it in the non-nil case, not use it in the nil case, but consume it in both cases.

Maybe it can be accomplished by consuming nil and printing it as ""? If so I don't know how to do that.

解决方案

The question you linked to, Lisp format directive that interprets nil argument to empty string instead of "NIL", does include an answer that shows how you can do this, but doesn't cite any of the documentation. Since you're generating English text, there are also a few other options that you might want to consider as well.

First, with ~@[consequent~], you can process the consequent format directive just in the case that the argument is non-nil, and the argument to ~@[ isn't consumed, so it's still available. In general, 22.3.7.2 Tilde Left-Bracket: Conditional Expression describes lots of options, but about ~@[ it says:

~@[consequent~] tests the argument. If it is true, then the argument is not used up by the ~[ command but remains as the next one to be processed, and the one clause consequent is processed. If the arg is false, then the argument is used up, and the clause is not processed. The clause therefore should normally use exactly one argument, and may expect it to be non-nil.

You can use this as follows:

(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."

To make this even more robust, you should consider using ~p for pluralization, so that you get "1 apple" and "3 apples".

(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."

Finally, since you're generating text, you might appreciate some case normalization (e.g., print proper nouns with initial capitals), and writing the numbers in text:

(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.")

这篇关于CL格式配方:处理nil作为值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆