嵌套引号在很大程度上是无用的。它可能发生在反引号语法的编译器的输出中,但我想不出你会这样做的任何理由,即使在嵌套宏中也是如此。如果您发现自己使用了级联引号,这可能意味着您在反引号模板中插入了错误的取消引用级别的表达式。
具体来说,假设你写了这样的东西:
````(,,,,'''''a) ;; goal is to be left with ('a) at the end of four eval rounds
但是在这里,逗号和引号基本上取消了,你可以这样做:
````('a)
无需将表单分配给''''a
最里面的反引号,并让它'a
在多个评估中反向工作。只需分配'a
到最外层即可。
另一个例子是对上述内容的轻微修改。我们预计会发生四轮评估,并在最后一轮a
替换它在评估环境中的绑定:
````(,,,,''''a) ;; only four quotes this time
所以现在,在上述反引号的结果的三个eval
s 之后,我们留下了(a)
,如果我们eval
这样,它想调用 function a
。但是,同样,我们可以实现同样的事情:
````(a)
和之前一模一样,三个evals
产生(a)
一个又一个想要跟注a
。
现在如果符号a
不是字面上的a
,而是计算出来的呢?说a
是被替换为b
:
(let ((a 'b))
````(,,,''',a))
替换必须发生在反引号的第一次求值中,在 , 里面let
,所以b
左边需要四个逗号,以便它连接到最外面的反引号。结果对象等价于
```(,,,'''a)
在这个例子中,我们不能只取消三个逗号和引号。但是,习惯的方式是让两者穿插:
(let ((a 'b))
````(,',',',a)) ;; instead of ,,,''',a
每一轮评估都会去掉一个报价,然后再加一个。第一个替换用 替换,a
,b
然后用引号保护它。然后在下一轮中,该引号之前的逗号会,'b
被替换为b
,但之前的另一个引号会再次保护它,依此类推。
也就是说,您可能会看到直接复合引号做一些有用的两种情况是:三重(或更多)嵌套反引号(很少开始!)其中有人使用,,'',expr
而不是,',',expr
; 以及多余地使用多个引号来对抗某种形式的多次评估,这些评估不必要地被淹没在多个评估轮次中。