要在一组 Lisp 对象中表示共享或循环结构,你可以使用读取器构造符 ‘#n=’ 和 ‘#n#’。
在一个对象前使用 #n= 可为其添加标签,以便后续引用;之后,你可以在其他位置使用 #n# 来引用同一个对象。其中 n 是某个整数。例如,以下写法可创建一个列表,使其第一个元素同时作为第三个元素出现:
(#1=(a) b #1#)
这与如下普通语法不同:
((a) b (a))
后者生成的列表中,第一个和第三个元素看起来相同,但并非同一个 Lisp 对象。以下代码可体现这种差异:
(prog1 nil
(setq x '(#1=(a) b #1#)))
(eq (nth 0 x) (nth 2 x))
⇒ t
(setq x '((a) b (a)))
(eq (nth 0 x) (nth 2 x))
⇒ nil
你也可以使用相同的语法创建循环结构(即对象自身包含自身作为元素)。示例如下:
#1=(a #1#)
这会创建一个列表,其第二个元素就是该列表本身。可通过以下方式验证其效果:
(prog1 nil
(setq x '#1=(a #1#)))
(eq x (cadr x))
⇒ t
若将变量 print-circle 绑定为非-nil 值,Lisp 打印器会生成此类语法,以记录 Lisp 对象中的循环和共享结构。See 影响输出的变量。