📝Common Lisp: Format

tags

Common Lisp

Directives basics

  • All directives start with a tilde (~) and end with a single char identifying the directive.

  • Some directives take prefix parameters written immediately after the tilde

    • parameters can be separated with comma

    • if parameter is a number, it is written as is

    • if parameter is a char, it is prefixed with single quote

    • v means parameter should be taken from the next format argument ((format t "~v$" 3 pi) prints 3.142)

    • # evaluates to the number of remaining format arguments

    • first parameters can be omitted, but you need to specify the comma

  • : and/or @ modifiers can be placed after parameters to modify the behavior of the directive

    • modifier can be combined

List of directives

~a

“aesthetics.” "Hello"Hello, :helloHELLO.

  • : — emit nil as () rather than NIL

~s

tries to convert to string that is read‘able

  • : — emit nil as () rather than NIL

~%

newline

  • first parameter: number of newlines to emit

~&

fresh line (emit a newline if not already at the beginning of a line)

  • first parameter: number of newlines to emit (will emit either n - 1 or n newlines)

~~

literal tilde

  • first parameter: how many tildes to emit

~$ ~n$

floating point

  • 1st parameter: print with up to n (default 2) decimal points

~c

character

  • : output non-printing chars as names. e.g., Space

  • @ output char in Lisp’s literal syntax. e.g., #\a

  • :@ also output additional information how to input the char ^@ (Control @)

    (format nil "~:@c" (code-char 32)) ; may output => "^@ (Control @)"
    

    This combination is not reliable though.

~d

decimal integer

  • : add commas between thousands

  • @ always print number sign

  • 1st parameter: minimum width for the output

  • 2nd parameter: padding character to use (default is space)

  • 3rd parameter: char to use as a separator for : (default ,)

  • 4th parameter: number of digits per group for : (default 3)

~x, ~o, ~b

work like ~d but in hexadecimal, octal, and binary

~r

(radix) same as ~d but allows to specify the base to use as an additional first parameter

  • without base, spell out as English words

  • no base + : — spell out as an ordinal (xth)

  • no base + @ — print out as a Roman numeral

  • no base + :@ — old-style Roman numeral (IIII instead of IV)

~f

floating pointer in decimal format but allowed to use computerized scientific notation

  • 2nd parameter: number of decimal digits after the decimal point

  • @ always print the sign

~e

same as ~f but is required to use computerized scientific notation

~$

(monetary)

  • 1st parameter: number of decimal digits after the decimal point (default 2)

  • 2nd parameter: minimum number of digits to print before the decimal point (padded with zeros)

  • @ always print the sign

~p

(pluralize) emits an s unless the argument is 1

  • : use previous argument instead of the current one

    (format nil "~r file~:p" 1)  ; => "one file"
    (format nil "~r file~:p" 10) ; => "ten files"
    (format nil "~r file~:p" 0)  ; => "zero files"
    
  • @ emit either y or ies

    (format nil "~r famil~:@p" 1)  ; => "one family"
    (format nil "~r famil~:@p" 10) ; => "ten families"
    (format nil "~r famil~:@p" 0)  ; => "zero families"
    
~( ~)

output in lowercase

  • @ — capitalize the first word and make the rest lowercase

  • : — capitalize all words

  • :@ — make uppercase

(format nil "~(~a~)" "tHe Quick BROWN foX")   ; => "the quick brown fox"
(format nil "~@(~a~)" "tHe Quick BROWN foX")  ; => "The quick brown fox"
(format nil "~:(~a~)" "tHe Quick BROWN foX")  ; => "The Quick Brown Fox"
(format nil "~:@(~a~)" "tHe Quick BROWN foX") ; => "THE QUICK BROWN FOX"
~10t

“tabulation.” Add spaces to move to N-th column.

~[ 0-case ~; 1-case … ~]

(conditional directive) use different format depending on value of the argument

  • if the last separator is ~:; it serves as a default value

  • : treat boolean as 0/1

  • 1st parameter of ~[ can specify the case to select (useful with #)

  • @ — the directive can only have one option that is printed if argument is non-nil. Backs up, so that argument can be consumed by the clause

    (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) ; => ""
    
~{ ~}

loop over the list, consuming as many elements as necessary

~^

within the list, stops processing the rest of control string when no elements remain in the list

(format nil "~{~a~^, ~}" (list 1 2 3)) ; => "1, 2, 3"
  • @ process the remaining format arguments as a list

    (format nil "~@{~a~^, ~}" 1 2 3) ; => "1, 2, 3"
    
  • ~*

    move to the next argument

    • : — move to the previous argument

    • 1st argument:

      • number of argument to move forward or backwards (depending on :)

      • with @ — absolute index of argument to jump to (default to 0)

    Backlinks