📝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