In Common Lisp FORMAT how does recursive formattin

2019-07-08 11:02发布

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?

1条回答
看我几分像从前
2楼-- · 2019-07-08 11:25

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.

查看更多
登录 后发表回答