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

wut*_*tch 12 lisp common-lisp string-formatting

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

也许像关联列表那样的东西

(format t "All for ~(who)a and ~(who)a for all!~%" ((who . "one")))
Run Code Online (Sandbox Code Playgroud)

为了打印"All for one and one for all".

类似于这个python问题,或者这个scala,甚至是c ++,但是在Lisp中.

如果此功能不在语言中,那么是否有人可以使用任何可以完成相同操作的酷函数或宏?

cor*_*ump 18

使用CL-INTERPOL.

(cl-interpol:enable-interpol-syntax)
Run Code Online (Sandbox Code Playgroud)

字符串插值

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

(lambda (who) #?"All for $(who) and $(who) for all!")
Run Code Online (Sandbox Code Playgroud)

然后:

(funcall * "one")
=> "All for one and one for all!"
Run Code Online (Sandbox Code Playgroud)

解释格式指令

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

(setf cl-interpol:*interpolate-format-directives* t)
Run Code Online (Sandbox Code Playgroud)

例如,这个表达式:

(let ((who "one"))
  (princ #?"All for ~A(who) and ~S(who) for all!~%"))
Run Code Online (Sandbox Code Playgroud)

...打印:

All for one and "one" for all!
Run Code Online (Sandbox Code Playgroud)

如果你很好奇,上面的内容如下:

(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))))
Run Code Online (Sandbox Code Playgroud)

备用读卡器功能

以前,我全局设置*interpolate-format-directives*,它解释所有插值字符串中的格式指令.如果要精确控制何时插入格式指令,则不能仅在代码中临时绑定变量,因为魔法发生在读取时.相反,您必须使用自定义阅读器功能.

(set-dispatch-macro-character
 #\#
 #\F
 (lambda (&rest args)
   (let ((cl-interpol:*interpolate-format-directives* t))
     (apply #'cl-interpol:interpol-reader args))))
Run Code Online (Sandbox Code Playgroud)

如果我将特殊变量重置为其默认值NIL,那么格式化指令的字符串将以前缀为前缀#F,而常规插值的字符串则使用该#?语法.如果您想更改readtables,请查看命名的readtables.

  • 我不使用它,但我听说CL Interpol需要我. (2认同)