Next: Jump Directive, Previous: Conditional Directive, Up: Controlled Formatting [Contents][Index]
This directive tells FORMAT
to iterate over the elements of a
list or over the implicit list of the format arguments. The text between the
two markers is processed as a control string, which draws its arguments from
the list consumed by the ‘~{’ directive. FORMAT
will repeatedly process
this control string for as long as the list being iterated over has elements
left.
Within the body of a ‘~{’ directive, the ‘~^’ causes the iteration to stop immediately, without processing the rest of the control string, when no elements remain in the list. Thus, to avoid printing the comma and space after the last element of a list, you can precede them with a ‘~^’.
(format nil "~{~a~^, ~}" (list 1 2 3)) ==> "1, 2, 3"
With an at-sign modifier, ‘~@{’ processes the remaining format arguments as a list.
(format nil "~@{~a~^, ~}" 1 2 3) ==> "1, 2, 3"
Within the body of a ‘~{...~}’, the special prefix parameter ‘#’ refers to the number of items remaining to be processed in the list rather than the number of remaining format arguments. You can use that, along with the ‘~[’ directive, to print a comma-separated list with an "and" before the last item like this:
(format nil "~{~a~#[~;, and ~:;, ~]~}" (list 1 2 3)) ==> "1, 2, and 3"
However, that doesn’t really work right if the list is two items long because it adds an extra comma.
The following takes advantage of the behavior of ‘~@{’ when nested inside another ‘~{’ or ‘~@{’ directive–it iterates over whatever items remain in the list being iterated over by the outer ‘~{’. You can combine that with a ‘~#[’ directive to make the following control string for formatting lists according to English grammar:
(defparameter *english-list* "~{~#[~;~a~;~a and ~a~:;~@{~a~#[~;, and ~:;, ~]~}~]~}")
If you wanted to print something special such as ‘<empty>’ when
the list was empty, you have a couple ways to do it. Perhaps the easiest is
to put the text you want into the first (zeroth) clause of the outer ‘~#[’
and then add a colon modifier to the closing ‘~}’ of the outer iteration–the
colon forces the iteration to be run at least once, even if the list is
empty, at which point FORMAT
processes the zeroth clause of the conditional
directive.
(defparameter *english-list* "~{~#[<empty>~;~a~;~a and ~a~:;~@{~a~#[~;, and ~:;, ~]~}~]~:}")
The ‘~{’ directive provides even more variations with different combinations of prefix parameters and modifiers. You can use an integer prefix parameter to limit the maximum number of iterations and that, with a colon modifier, each element of the list (either an actual list or the list constructed by the ‘~@{’ directive) must itself be a list whose elements will then be used as arguments to the control string in the ‘~:{...~}’ directive.
Next: Jump Directive, Previous: Conditional Directive, Up: Controlled Formatting [Contents][Index]