Книга: Practical Common Lisp

Conditional Formatting

Conditional Formatting

In addition to directives that interpolate arguments and modify other output, FORMAT provides several directives that implement simple control constructs within the control string. One of these, which you used in Chapter 9, is the conditional directive ~[. This directive is closed by a corresponding ~], and in between are a number of clauses separated by ~;. The job of the ~[ directive is to pick one of the clauses, which is then processed by FORMAT. With no modifiers or parameters, the clause is selected by numeric index; the ~[ directive consumes a format argument, which should be a number, and takes the nth (zero-based) clause where N is the value of the argument.

(format nil "~[cero~;uno~;dos~]" 0) ==> "cero"
(format nil "~[cero~;uno~;dos~]" 1) ==> "uno"
(format nil "~[cero~;uno~;dos~]" 2) ==> "dos"

If the value of the argument is greater than the number of clauses, nothing is printed.

(format nil "~[cero~;uno~;dos~]" 3) ==> ""

However, if the last clause separator is ~:; instead of ~;, then the last clause serves as a default clause.

(format nil "~[cero~;uno~;dos~:;mucho~]" 3) ==> "mucho"
(format nil "~[cero~;uno~;dos~:;mucho~]" 100) ==> "mucho"

It's also possible to specify the clause to be selected using a prefix parameter. While it'd be silly to use a literal value in the control string, recall that # used as a prefix parameter means the number of arguments remaining to be processed. Thus, you can define a format string such as the following:

(defparameter *list-etc*
"~#[NONE~;~a~;~a and ~a~:;~a, ~a~]~#[~; and ~a~:;, ~a, etc~].")

and then use it like this:

(format nil *list-etc*) ==> "NONE."
(format nil *list-etc* 'a) ==> "A."
(format nil *list-etc* 'a 'b) ==> "A and B."
(format nil *list-etc* 'a 'b 'c) ==> "A, B and C."
(format nil *list-etc* 'a 'b 'c 'd) ==> "A, B, C, etc."
(format nil *list-etc* 'a 'b 'c 'd 'e) ==> "A, B, C, etc."

Note that the control string actually contains two ~[~] directives—both of which use # to select the clause to use. The first consumes between zero and two arguments, while the second consumes one more, if available. FORMAT will silently ignore any arguments not consumed while processing the control string.

With a colon modifier, the ~[ can contain only two clauses; the directive consumes a single argument and processes the first clause if the argument is NIL and the second clause is otherwise. You used this variant of ~[ in Chapter 9 to generate pass/fail messages, like this:

(format t "~:[FAIL~;pass~]" test-result)

Note that either clause can be empty, but the directive must contain a ~;.

Finally, with an at-sign modifier, the ~[ directive can have only one clause. The directive consumes one argument and, if it's non-NIL, processes the clause after backing up to make the argument available to be consumed again.

(format nil "~@[x = ~a ~]~@[y = ~a~]" 10 20) ==> "x = 10 y = 20"
(format nil "~@[x = ~a ~]~@[y = ~a~]" 10 nil) ==> "x = 10 "
(format nil "~@[x = ~a ~]~@[y = ~a~]" nil 20) ==> "y = 20"
(format nil "~@[x = ~a ~]~@[y = ~a~]" nil nil) ==> ""

Оглавление книги


Генерация: 0.058. Запросов К БД/Cache: 0 / 0
поделиться
Вверх Вниз