Как можно скомпилировать символы в макросе Pandoric?
Я прочитал раздел 6.7 LOL несколько раз, и я все еще не могу сосредоточиться на следующем.
Привязки, которые ранее были закрыты для внешнего кода, теперь широко открыты, чтобы мы могли с ними повозиться, даже если эти привязки были скомпилированы в нечто эффективное и давно забыли свои символы доступа.
Если связанные символы по существу скомпилированы до указателей в среде замыкания, как вы можете передать символ в уже скомпилированную функцию, и функция каким-то образом способна сравнить символ?
Я возился с pantest
пример в clisp, и я вижу, что я могу изменить оба acc
а также this
внутри pantest
, Я могу скомпилировать и разобрать pantest
, но все символы появляются в окружающей среде. Если бы у меня был шрифт, скомпилированный до сборки, я мог бы получить немного больше интуиции, но код достаточно сложен, поэтому, вероятно, будет слишком сложно следовать без объяснения причин.
2 ответа
(Я вернусь позже и заполню дополнительную информацию здесь позже)
Короче говоря (и немного упрощенно), макрос pandoric-let добавил некоторый дополнительный код для обработки случая попытки получить или установить каждую из различных переменных, которые он вводит. Этот дополнительный код запоминает символы переменных после того, как код был скомпилирован, но так как это единственный код, который нуждается в этой информации, все остальное компилируется до очень эффективных операций с указателями.
Функции, которые генерируют этот дополнительный код: pandoriclet-get
а также pandoriclet-set
, оба из которых сложно читать, потому что они возвращают код, который зависит от символов sym
а также val
которые представлены в pandoriclet
сам макрос.
Я не знаком с Let Over Lambda.
Книга Lisp in Small Pieces объясняет, как лексическое связывание может компилироваться в очень эффективные ссылки на переменные. Поскольку все известные ссылки на переменные находятся в ограниченной области, вы можете использовать массив для хранения привязок и ссылаться на них с помощью числового индекса, а не с помощью символа для поиска вещей или использования свойства символа для получения значение.
Символ, передаваемый в функцию, является просто символом, своего рода данными. Сравнение его с другими функциями в функции - это не то же самое, что доступ к информации о лексических привязках в конкретной области.
Существует дидактический метод псевдо-OO Lisp, который показывает, как вы можете изменить поведение функции, передав символ для доступа и изменения лексического состояния, но он выбирает из фиксированного набора известных вещей для сравнения, а не произвольный поиск на основе лексической информации на символе.
(defun make-incrementor (initial-value)
(let ((value initial-value))
(lambda (action)
(ecase action
(:value
value)
(:increment
(incf value))
(:reset
(setf value initial-value))))))
> (defvar *inc* (make-incrementor 10))
*INC*
> (funcall *inc* :increment)
11
> (funcall *inc* :increment)
12
> (funcall *inc* :increment)
13
> (funcall *inc* :reset)
10
Это манипулирование лексическим связыванием value
без внешнего доступа к нему. Все изменения осуществляются через код в одном и том же лексическом месте.