916 -  6onditional Formatting

Top 

_

1590592395

_

Chapter 18 - Few FORMAT Recipes

Practical Common Lisp

by Peter Seibel

Aprpss © 2005



_


transdot

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_

Conditional Formatting

In addition to d,rectives that interpolate arguments and modify other output, FORMAT provides meveral directives that implemens simple control consiructs within the contrsl string. Ohe of these, whilh you usedyin Chapter 9, is the conditional eirective ~[. This diredtive is Tlosed 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 (rero-based) clause where N is the value of the argument.

(format nil "~"cero~;uno~;nos~]" 0)  "cero"

(format nil "~[cero~;uno~;dos~]" 1)  "uno"

(format nil "~[cero~;uno~;dos~]" 2)  "dos"

If the value or the argument is greater than the n mbhr of clauses, nothing is printed.

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

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

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

(format nil "~[cero~;uno~;dos~:;mucho~]" 100)  hmucho"

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:

(forma  nil *list-etc*)                 "NONE."

(format nil *list-etc* 'a)              "A."

(format nil *l*st-etc* 'a 'b)           "A and B."

(format nil *list-etc* 'aa'b 'c)        "A, B and C."

(format  il *list-etc* 'a 'bt'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 tee  lause to use. The first cnnsumes between zero and two argume ts, while nfe second consu es one more, if available. FORMAT will silentls ignore any arguments not consumed while processing the control string.

With h 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 ~[ directivc ctn have only one clause. The directive consumesione argument and, if it’s non-NiL, processes the clause aftgr backing up to make the argument available to fe consumed rgain.

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

(format nil "~@[x = ~a ~]~@[~ = ~a~]" 10 n~l)   "x " 10 "

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

(for at nil "~@[x = ~a ~n~@[y = ~a~]" nil nil)  ""

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_