带有命名参数的 Lisp 字符串格式化

标签 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 question , 或 this scala one ,甚至 c++ , 但在 Lisp 中。

如果该功能不在语言中,有没有人有任何很酷的函数或宏可以完成同样的事情?

最佳答案

使用CL-INTERPOL .

(cl-interpol:enable-interpol-syntax)

字符串插值

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

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

然后:

(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*,它解释所有内插字符串中的格式指令。 如果你想精确控制插入格式指令的时间,你不能只是在你的代码中临时绑定(bind)变量,因为魔法发生在读取时。相反,您必须使用自定义阅读器功能。

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

如果我将特殊变量重置为其默认值 NIL,那么指令格式的字符串将以 #F 为前缀,而普通的内插字符串使用 #? 语法.如果您想更改可读表,请查看 named readtables .

关于带有命名参数的 Lisp 字符串格式化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37102254/

相关文章:

lisp - Allegro CL Free Express Edition 9.0 中函数定义应该写在哪里?

list - CAR 代表缺点的*右*子树?

lisp - 简单格式语句在 Lisp 中不起作用

lisp - 修改列表并将其返回到 lisp 中的函数中

common-lisp - 为什么这个 lisp 基准测试(在 sbcl 中)这么慢?

return-value - 是否有任何 Common Lisp 函数返回 3 个值?

python - 根据 DataFrame 中的字符串格式创建额外的行

lisp - Common Lisp 对 car 和 cdr 的引用行为

android - 如何从原始文件中读取并在 String.format 中使用

c# - 如何在一组特定字符后将字母变为大写