使用命名参数的Lisp字符串格式

时间:2016-05-08 16:42:38

标签: lisp common-lisp string-formatting

Lisp中有没有办法使用命名参数格式化字符串?

也许是像

这样的关联列表
(format t "All for ~(who)a and ~(who)a for all!~%" ((who . "one")))

以便打印"All for one and one for all"

this python questionthis scala one,甚至c++类似,但在Lisp中。

如果此功能不在语言中,是否有人可以使用任何可以完成同样功能的酷炫功能或宏?

1 个答案:

答案 0 :(得分:18)

使用CL-INTERPOL

(lambda (who) #?"All for $(who) and $(who) for all!")

字符串插值

对于简单的情况,您不需要FORMAT

(funcall * "one")
=> "All for one and one for all!"

然后:

(setf cl-interpol:*interpolate-format-directives* t)

解释格式指令

如果您需要格式化,可以执行以下操作:

(let ((who "one"))
  (princ #?"All for ~A(who) and ~S(who) for all!~%"))

例如,这个表达式:

All for one and "one" for all!

...打印:

(LET ((WHO "one"))
  (PRINC
    (WITH-OUTPUT-TO-STRING (#:G1177)
      (WRITE-STRING "All for " #:G1177)
      (FORMAT #:G1177 "~A" (PROGN WHO))
      (WRITE-STRING " and " #:G1177)
      (FORMAT #:G1177 "~S" (PROGN WHO))
      (WRITE-STRING " for all!" #:G1177))))

如果您好奇,上面的读取

*interpolate-format-directives*

备用阅读器功能

以前,我全局设置(set-dispatch-macro-character #\# #\F (lambda (&rest args) (let ((cl-interpol:*interpolate-format-directives* t)) (apply #'cl-interpol:interpol-reader args)))) ,它解释所有插值字符串中的格式指令。 如果要精确控制何时插入格式指令,则不能在代码中临时绑定变量,因为魔术在读取时发生。相反,您必须使用自定义阅读器功能。

#F

如果我将特殊变量重置为其默认值NIL,则格式化指令的字符串以#?为前缀,而普通插值的字符串使用{{1}}语法。如果您想更改阅读表,请查看named readtables