在Common Lisp FORMAT中,递归格式化如何工作

时间:2018-02-19 14:44:24

标签: format common-lisp

我需要生成一个带有可变字符串长度的空格填充字符串。不那么聪明的解决方案涉及嵌套format

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

现在,我希望通过使用format' s ~?进行递归处理,使其变得更加聪明。我希望像这样的东西应该做我想做的事情:

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

但我得到的只是格式化字符串,即~10,,a,而不是填充的asdf字符串。也许我误解了“递归”这个词。在这里,但我希望已经形成了内部格式字符串,CL应该继续实际使用它。我错过了什么吗?

1 个答案:

答案 0 :(得分:5)

格式指令的变量参数

FORMAT允许您使用v作为控制字符串中指令的参数,以从参数列表中弹出参数。

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

可能会使用多个v

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

使用~?

进行递归处理

递归处理指令用于在控件字符串中嵌入对FORMAT的不同“调用”。例如,可以使用它来实现提示是或否答案的函数。

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

调用者现在可以使用FORMAT格式化提示,而不必担心提示应该对用户的详细信息(在开头添加新行或{{ 1}}提示结束)。

[y/n]:

CL-USER> (y-or-n-prompt "foo ~d bar" 12) foo 12 bar [y/n]: NIL 的结果将不会由~?处理,因此无法用于构建控制字符串。通常,在运行时构建控制字符串是一个坏主意,因为它容易出错(例如,您必须转义字符串中任何不需要的波形)并阻止实现在编译时处理控制字符串。