Hacker News new | ask | show | jobs
by db48x 16 days ago
`printf` with some GNU extensions is accidentally Turing–complete because you can overwrite it's internal state. Common Lisp’s `format` is intentionally and safely Turing–complete because it includes directives for conditionals, iteration, goto, and recursion. The classic example for printing lists:

    (setq foo "Items:~#[ none~; ~S~; ~S and ~S~
              ~:;~@{~#[~; and~] ~S~^ ,~}~].")
    (format nil foo) =>   "Items: none."
    (format nil foo 'foo) =>   "Items: FOO."
    (format nil foo 'foo 'bar) =>   "Items: FOO and BAR."
    (format nil foo 'foo 'bar 'baz) =>   "Items: FOO, BAR, and BAZ."
    (format nil foo 'foo 'bar 'baz 'quux) =>   "Items: FOO, BAR, BAZ, and QUUX."
<https://www.lispworks.com/documentation/HyperSpec/Body/22_cg...>

The directives for recursion takes a format string and a list, calls `format` on the string using the list as the list of arguments and then inserts the result into the current output. This is much less verbose than calling `snprintf` to create a temporary string and then insertimg it into the current output with %s. <https://www.lispworks.com/documentation/HyperSpec/Body/22_cg...>

There is also a directives for calling a Lisp function to print the next argument, and the standard library includes several functions intended to be called from within a format string. <https://www.lispworks.com/documentation/HyperSpec/Body/22_ce...>