CL Recipe Format: Working with Zero as a Value

I was looking through formatting recipes and I cannot find what I was looking for ...

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

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

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

When name is zero, I want the result to look like

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

but when name defined, I want it to look like

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

Thus, the control string should look at name , use it in a case other than zero, and not use it in the case of nil, but consume it in both cases.

Perhaps this can be achieved by consuming nil and printing it as "" ? If so, I do not know how to do it.

+6
source share
1 answer

The question you're related to is the Lisp format directive, which interprets the nil argument for an empty string instead of "NIL" , includes an answer that shows how you can do this, but does not refer to any documentation. Since you are generating English text, there are also a few other options that you might want to consider.

Firstly, with ~ @ [sequence ~], you can only process a sequential format directive if the argument is non-zero and the ~ @ [ argument is not consumed, so it is still available. In general, 22.3.7.2 Tilda's left bracket: the conditional expression describes many options, but roughly ~ @ [ says:

~ @ [followend ~] checks the argument. If this is the case, then the argument is not used by the [[] command, but the next sentence is processed and processed. If arg is false, then the argument is used and the sentence is not processed. Therefore, you should usually use only one argument in this article, and perhaps expect it to be non-zero.

You can use it 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 reliable, you should use ~ p for pluralization so that you get "1 apple" and "3 apple 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." 

Finally, since you are generating text, you can evaluate some normal situation (for example, print your own nouns with seed capital) and write the numbers in the 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.") 
+9
source

All Articles