Lisp中有没有办法使用命名参数格式化字符串?
也许是像
这样的关联列表(format t "All for ~(who)a and ~(who)a for all!~%" ((who . "one")))
以便打印"All for one and one for all"
。
与this python question或this scala one,甚至c++类似,但在Lisp中。
如果此功能不在语言中,是否有人可以使用任何可以完成同样功能的酷炫功能或宏?
答案 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。