Wojciech Gac
Wojciech Gac

Reputation: 1576

In Common Lisp FORMAT how does recursive formatting work

I need to generate a space-padded string with a variable string length. The not-so-clever solution that works involved nesting of format:

(format nil (format nil "~~~d,,a" 10) "asdf")

Now, I wanted to make it a bit more clever by using format's ~? for recursive processing. I would expect that something like this should do what I want:

(format nil "~@?" "~~~d,,a" 10 "asdf")

but what I get is just the formatting string, i.e. ~10,,a, not the padded asdf string. Perhaps I misunderstood the word 'recursive' here, but I would expect that having formed the inner format string, CL should proceed to actually use it. Am I missing something?

Upvotes: 1

Views: 502

Answers (1)

jkiiski
jkiiski

Reputation: 8421

Variable arguments to format directives

FORMAT allows you to use v as an argument to a directive in the control string to pop arguments from the argument list.

CL-USER> (format nil "~va" 10 "asdf")
"asdf      "

There may be multiple vs used.

CL-USER> (format nil "~v,,,va" 10 #\- "asdf")
"asdf------"

Recursive processing with ~?

The recursive processing directive is meant for embedding a different "call" to FORMAT inside a control string. For example, a function to prompt for a yes or no answer might be implemented with it.

(defun y-or-n-prompt (control-string &rest args)
  (format t "~&~? [y/n]: " control-string args)
  ;;...
  )

The caller can now format a prompt with this as they would with FORMAT without having to worry about the details of what the prompt should look like to the user (adding a new line at the beginning or the [y/n]: prompt at the end).

CL-USER> (y-or-n-prompt "foo ~d bar" 12)
foo 12 bar [y/n]: 
NIL

The result of ~? will not be processed by FORMAT, so it cannot be used to build a control string. In general, building control strings at run time is a bad idea, because it's error prone (for example, you must escape any unwanted tildes in the string) and prevents the implementation from processing the control string at compile time.

Upvotes: 5

Related Questions