The format string str
within ~{str~}
can use up more than one argument from the list on each iteration. This means that if you had a list of arguments guaranteed to be divisible by three, you could use a format string like ~{~a ~a ~a~%~}
. Here's an example:
CL-USER> (format nil "~{~a ~a ~a~%~}" '(1 2 3 4 5 6))
"1 2 3
4 5 6
"
You might have a number of arguments that's not divisible by three, though, in which case you'd need to terminate an iteration early. You can use the format directive ~^
to break if there are no more arguments. Since you might end up in this situation after the first or second argument, you should add one of these after those places. Here are examples for cases with zero, one, and two trailing arguments:
CL-USER> (format nil "~{~a~^ ~a~^ ~a~%~}" '(1 2 3 4))
"1 2 3
4"
CL-USER> (format nil "~{~a~^ ~a~^ ~a~%~}" '(1 2 3 4 5))
"1 2 3
4 5"
CL-USER> (format nil "~{~a~^ ~a~^ ~a~%~}" '(1 2 3 4 5 6))
"1 2 3
4 5 6
"
You might not want that final newline when there the number of elements is divisible by three, in which case you can add a ~^
before the newline, too:
CL-USER> (format nil "~{~a~^ ~a~^ ~a~^~%~}" '(1 2 3 4 5 6))
"1 2 3
4 5 6"
This kind of construct is particularly nice for writing delimited lists:
CL-USER> (format nil "write(~{~a~^,~})" '("fd" "buf" "count"))
"write(fd,buf,count)"
These format directives (and their variants) are described in more detail in the HyperSpec (there's more in the linked page than what's quoted here):
~{str~}
This is an iteration construct. The argument should be a list, which
is used as a set of arguments as if for a recursive call to format.
The string str is used repeatedly as the control string. Each
iteration can absorb as many elements of the list as it likes as
arguments; if str uses up two arguments by itself, then two elements
of the list will get used up each time around the loop. If before any
iteration step the list is empty, then the iteration is terminated.
Also, if a prefix parameter n is given, then there will be at most n
repetitions of processing of str. Finally, the ~^
directive can be
used to terminate the iteration prematurely.
You might also be interested in these questions:
(format t "hello there~cj" #\return)
, I seejello there
on the screen, but after(format t "hello there~cj" #\newline)
, I see two lines, the first of which ishello there
and the second of which isj
. – Contradistinction