在遍历一组格式化的子列表时,在最后一次迭代中省略一个字符

编程语言 2026-07-11

可以通过在最后一次迭代的格式化输出前面加上 ~^ 格式指令来省略一个字符:

(format nil "~{~A~^,~}" '(1 2 3))
;; -> "1,2,3"

也可以对一个子列表的列表进行迭代,逐个使用其中的每个子列表的值:

(format nil "~:{~A is for ~A. ~}" '(("A" "Alice") ("B" "Bob")))
;; -> "A is for Alice. B is for Bob. "

但将两者结合起来似乎行不通(在SBCL和 CLisp上测试过):

(format nil "[~:{[~d,~d]~^,~}]" '((1 2) (3 4)))
;; -> "[[1,2][3,4]]" instead of "[[1,2],[3,4]]"

有没有办法实现这一点?

解决方案

对于 ~:{(以及 ~:@{ 这样的构造,使用该目的的正确格式指令是 ~:^,而不是 ~^

根据 CLHS的 2.3.9.2 "Tilde Circumflex: Escape Upward":

如果 ~^~:{ 构造中使用,则会终止当前迭代步骤,因为在标准情况下它只测试当前步骤的剩余参数;下一次迭代步骤会立即开始。~:^ 用于终止迭代过程。~:^ 仅在它将终止的命令是 ~:{~:@{ 时才可使用。

所以看起来我可以直接执行以下操作:

(format nil "[~:{[~d,~d]~:^,~}]" '((1 2) (3 4)))
;; -> "[[1,2],[3,4]]"
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章