2.6 Синтаксис чтения для циклических объектов

Чтобы представить общие или циклические структуры в комплексе 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

Принтер Lisp может выводить этот синтаксис для записи циклической и общей структуры в Lisp-объекте, если вы привяжете переменную print-circle к значению, отличному от nil. См. Переменные, влияющие на вывод.