format
(format destination control-string args...)
A minimal subset of Common Lisp's format, implemented as a macro shared by the
interpreter and both compilers. The control-string must be a literal: with
destination t the form expands into princ/prin1/terpri calls, writes to
standard output, and returns nil; with destination nil it builds and returns
the formatted string (expanding into princ-to-string/prin1-to-string calls
folded with the internal string concatenation); with any other destination
expression it builds the string the same way, writes it to the stream with one
write-string call, and returns nil (a with-output-to-string string stream or
a file stream). All arguments are evaluated left to right before any output.
Hello world, you are 42!
With destination nil the result is returned as a string instead of printed:
Directives
| Directive | Meaning |
|---|---|
~a, ~A | Aesthetic: prints the argument like princ (strings without quotes). With :, nil prints as () |
~s, ~S | Standard: prints the argument like prin1 (readable, strings quoted). With :, nil prints as () |
~d, ~D | Decimal integer. With :, digits are grouped with commas; with @, a + sign precedes non-negative values |
~x, ~o, ~b | Hexadecimal / octal / binary integer (uppercase digits), with the same parameters and modifiers as ~d |
~R | Radix: ~NR prints the integer in radix N (2-36). The radix parameter is required (English cardinal/ordinal output is not implemented) |
~c, ~C | Character: prints the glyph like write-char. With @, the #\ reader syntax (like prin1); with :, non-graphic characters print their name (Newline, Space, ...) |
~f, ~F | Fixed-format floating point. ~,Df prints D digits after the decimal point (rounded); with @, a leading +. Full parameters: ~w,d,k,overflowchar,padchar F |
~e, ~E | Exponential (scientific) floating point: [-]d.ddde[+/-]xx. ~,De prints D digits after the decimal point (default 6, rounded); with @, a leading +. Full parameters: ~w,d,e,k,overflowchar,padchar,exponentchar E (k must be 1) |
~g, ~G | General floating point: the plain float representation for magnitudes in [0.1, 1e16) (and zero), the ~e form otherwise |
~$ | Monetary: ~D$ prints D digits after the decimal point (default 2); with @, a leading + |
~% | Newline (one, or the count given by a prefix parameter) |
~& | Fresh line: a newline only if not already at the start of a line |
~~ | A literal ~ |
~(str~) | Case conversion of the processed str: downcase; ~:( capitalizes every word, ~@( capitalizes only the first word, ~:@( upcases |
~[str0~;str1~:;default~] | Conditional: the argument (an integer) selects a clause; ~:; introduces the default. ~N[ / ~#[ select by a literal / by the number of remaining arguments; ~:[false~;true~] tests nil; ~@[str~] processes str (re-using the tested argument) only when it is non-nil |
~{str~} | Iteration: applies str repeatedly to the elements of the list argument. ~N{ caps the passes at N; ~:{ iterates over a list of sublists; ~@{ iterates over the remaining arguments; ~:@{ treats each remaining argument as a sublist |
~* | Argument jump: ~N* skips N arguments (default 1), ~N:* moves back N, ~N@* jumps to argument N (default 0) |
Directives accept prefix parameters (written after the ~, comma-separated) and
the :/@ modifiers. A parameter is a decimal number, a character ('c), v
(consume an argument and use its value), or # (the number of remaining
arguments). Field directives (~a/~s/~d/~x/~o/~b/~f/~e/~$) take
a leading minimum-width parameter; text shorter than the width is padded (with
the pad-character parameter -- a 'c literal or a runtime v -- space by
default). ~a/~s pad on the right (left with @); numbers pad on the left.
Hello world, you are 42 years old.
1,000,000 and +42
3.14 and 3.14
1.2345e+3 and 3.1416e+0
foo |00042|
Hello world!
FF 100 101 10000
a #\b Newline
foo bar Foo Bar
one yes x=42
<1><2> (x,1)(y,2) a b
1 1
Limitations
Other destinations (streams, strings with fill pointers) are not supported, the
control string cannot be a runtime value, and the column-control directives
(~t, ~<...~>), the loop escape ~^, and ~r without a radix parameter are
not implemented. Further notes:
- A
~f(and the fixed branch of~g) without a digit count falls back to each backend's native float printing, so its exact form is backend-specific; supply a digit count for portable output.~gaccepts no prefix parameters. ~ebuilds its mantissa from integer arithmetic (so the output is identical on every backend) and the digit count must be a literal, not a runtimev. Because the WASM backend caps integers at the i31 range, the scaled mantissa limits~,Deto roughlyD≤ 8 digits of precision; the default (~e, 6 digits) is well within that bound. The scale factor of~emust be 1 (the default), and the overflow character of~f/~erequires a literal width.- The repeat count of
~%/~&/~~must be a literal or#(a runtimevcount there is not supported).~&decides whether to emit a newline from the actual output column for destinationt, but from the surrounding literal text (a static approximation) for destinationniland inside composite (~(/~[/~{) bodies. - Because
formatexpands statically, a runtime-selected~[requires every clause to consume the same number of arguments (a literal or#selector lifts that restriction), a~@[clause must consume exactly the tested argument, and#and~@{are not available inside a~{ ... ~}body. - On the WASM backend integers are limited to the i31 range, so
~:dgrouping of very large (bignum) integers (and~x/~o/~b/~rof such values) works only in the interpreter and the JVM backend.
Like the other macros, format is not recognized by the embedded eval runtime
in compiled output (see Compiled eval limitations).