Как семантика "лексическая и специальная переменная" реализуется вообще под капотом?
CLtL2 прояснил различие между областью применения и объемом. В отношении лексических и специальных переменных я полагаю, что лексические переменные "лексически ограничены с неопределенной степенью", а специальные переменные "неопределенно ограничены динамическим расширением".
Мой вопрос: как семантика "лексической и специальной переменной" реализуется в целом? Под "в целом" я подразумеваю, что достаточно общей идеи. Учитывая долгую историю Lisp, для реализации этих базовых концепций должны быть применены многочисленные оптимизации.
Чтобы начать обсуждение, я рискну предположить ниже.
Все начинается со среды. Среда - это последовательность кадров, причем каждый кадр представляет собой таблицу, которая отображает имена в местах (значение которых можно извлечь и сохранить); каждое такое отображение - это привязка имени к месту. Кадры связаны вложенными отношениями; имя во внутренней рамке может скрывать то же имя во внешней рамке. Кроме того, привязки в Common Lisp по умолчанию являются лексическими, если declare
-d /declaim
-ed /proclaim
должен быть особенным.
Существует два аспекта семантики: поиск имени и создание новой привязки.
Создайте новую привязку.
lambda
выражения,let
/let*
,labels
/flet
,macrolet
и макросы, использующие их, создают привязки. Лексическая привязка создается путем создания нового фрейма и наличия текущей лексической среды, которая будет окружением нового фрейма. Специальная привязка (которая должна быть явно объявлена) перемещает новое место на вершину стека, созданного для имени в текущем пакете (стек может быть расположен, возможно, с помощью хеш-таблицы по именам) - стек используется для реализации динамический экстент, так что при выходе из конструирующей формы привязка может быть разобрана путем выталкивания стека (вопрос заключается в том, как это обеспечить, возможно, с помощью чего-то вродеunwind-protect
под капотом?).Поиск имени. Если явно не указано, что он особенный, поиск имени по умолчанию выполняется на основе поиска в лексической среде - через ссылку кадра, которая была установлена во время создания привязки. Первое совпадающее имя в процессе поиска выигрывает. Для специальных имен (которые должны быть явно объявлены так), поиск обслуживается путем просмотра вершины стека.
1 ответ
Я думаю, что этот вопрос, вероятно, будет перенесен на http://programmers.stackexchange.com/, но есть и другие вопросы о Stackru, в которых даются ответы на некоторые из этих вопросов, хотя ни один из найденных мной до сих пор не является точной копией. Посмотри на:
- Как реализуется Lexical Scoping?
- Возможно ли иметь жесткий режим реального времени с лексической областью?
- Лексическая и динамическая область видимости с точки зрения экологической модели оценки SICP
Кроме того, что бы это ни стоило, вы, вероятно, обнаружите, что в скомпилированных языках "поиск" лексической среды на самом деле не требует большого поиска и может быть скомпилирован в постоянную ссылку на память в лексическую среду (которая все еще является своего рода поиска, но вся работа определяется заранее, и только поиск должен происходить во время выполнения).