如何把不完整的 backquote 表达式原样转为字符串?

完整的表达式是符合预期的:

(format "%S" '`(foo a b ,@(c 1 2)))
;; actual   => "`(foo a b ,@(c 1 2))"
;; expected => "`(foo a b ,@(c 1 2))"

但是不完的整表达式却出现字符被转义的问题:

(format "%S" '(foo a b ,@(c 1 2)))
;; actual   => "(foo a b (\\,@ (c 1 2)))"
;; expected => "(foo a b ,@(c 1 2))"

在 CL 里第二个那样 misplaced comma 是可能在 read time/eval time 报错的。

cl 的确比较严格:

#+BEGIN_SRC lisp :results output :playonline
(format "%S" '(foo a b ,@(c 1 2)))
#+END_SRC

#+RESULTS:
: *** - READ: comma is illegal outside of backquote

%S来打印只会保证除了opaque object(如buffer) 以外的code structure, 用read 读入时会保持原样.

至于为啥被转义了, 因为` , ,@ 这些reader本来就要展开成对应名字的宏才能有作用

(equal `(,@'(1 2 3 4) ,@'(7 8 9))
       (\` ((\,@ (quote (1 2 3 4))) (\,@ (quote (7 8 9))))))
;; => t

刚才测试可以用cl-printcl-prin1

(cl-prin1-to-string '(test ,'(1 2 3 4) ,@'(7 8 9)))
;; => "(test ,'(1 2 3 4) ,@'(7 8 9))"

1 个赞

26.1 才有 cl-prin1,看来只能自己照着抄一个简版的了。