Дуглас Хофстадтер трижды вёл колонки в Scientific American в 1983 году, объясняя читателям Lisp, и начинал с простого тезиса: на Lisp написано большинство AI-разработок, потому что Lisp — «чёткий», элегантный. Автор статьи замечает, что это не случайно: Lisp — самая «ГЭБ-образная» вещь в программировании.
В основе GEB лежит гёделевская нумерация: высказывания об арифметике кодируются как сама арифметика, пока теория чисел не начинает говорить о себе. Гёдель строил мост между мирами предложений и чисел. А в Lisp этот мост будто встроен: программа уже является структурой данных. В «Гёделе, Эшере, Бахе» Краб прямо говорит: в LISP можно говорить о своих программах напрямую, потому что программы и данные имеют одну и ту же форму, — Гёдель просто должен был придумать LISP. Но Хофстадтер обрывает его: никакая ссылка не бывает по-настоящему прямой, у любой схемы кодирования есть код. Lisp не отменил гёделев мост, он просто спрятал его глубоко под синтаксис.
Любимое понятие Хофстадтера — «странная петля»: поднимаясь по уровням иерархической системы, неожиданно оказываешься там, откуда начал. Эшеровские «Рисующие руки» — канонический образ: одна рука рисует другую, каждая и художник, и рисунок. Elisp прячет эту литографию в собственной загрузке: defmacro, форма для создания макросов, сама является макросом. Проверка (macrop 'defmacro) возвращает t.
Петли вложены глубже. Макрос может раскрываться в код, содержащий новые макросы. В статье есть пример deftoggles: он определяет команды-переключатели для списка переменных и разворачивается сначала в deftoggle, потом в defun, потом в defalias. Программа пишет программу, которая пишет программу, которая пишет программу. Хофстадтер описывал интерпретатор Lisp как джинна, исполняющего желания; макрос — это желание, объектом которого становится новое желание.
Такое раскрытие напоминает «Галерею» Эшера: гравюра с морским портом разрастается и вбирает галерею и зрителя. Каждый уровень макроса — картинка, внутри которой оказывается комната, где ты стоишь. Эшер не смог завершить эту петлю: в центре он оставил белое пятно и поставил подпись. У Elisp тоже есть такое пятно — special forms, где язык перестаёт быть написанным на себе и переходит в C.
У «Рептилий» Эшера ящерица вылезает из плоского рисунка, становится объёмной, обходит книгу и додекаэдр, а потом ныряет обратно в страницу. Это в точности quote и eval: процитированная форма — ящерица на бумаге, eval оживляет её. Макросы работают с бумажными рептилиями, переставляя рисунки будущего кода.
В Lisp символы — полноценные объекты первого класса. И каждый этаж башни раскрытия говорит на своём языке: use-package — на языке конфигурации, следующий уровень — хуки и клавиатурные раскладки, ниже — управление потоком. Смысл конденсируется снизу доверху, и ни один этаж не «настоящий». Зато с Emacs можно кататься по этой башне в любую сторону.