Время привязки свободных переменных указанных терминов в схеме
Я пытаюсь понять, как работает феномен цитаты в Схеме. В частности, я хотел бы понять, когда связаны свободные переменные цитируемых терминов.
Например, когда я пишу
(define q 'a)
(define a 42)
(eval q)
он возвращает 42. Таким образом, я делаю вывод, что время привязки находится во время выполнения. Но в этом случае, почему этот код не работает
(let ((q 'a))
(let ((a 42))
(eval q)
)
)
и возвращается
unbound variable: a
Может кто-нибудь объяснить мне, какова модель времени привязки цитируемых терминов (например, сопоставима ли она с MetaOCaml? (Я так не думаю)) и в чем разница между define и let?
2 ответа
Схема имеет лексическую дисциплину, а не динамическую дисциплину.
Ваш верхний уровень define
определения ведут себя так, как будто создают привязку в лексической среде верхнего уровня.
Второй фрагмент кода фактически создает две лексические среды, одна вложенная в другую. Так где (не "когда") q
связан, a
все еще не связан. Но реальный вопрос в том, какая среда используется eval
?
Ваша реализация ведет себя так, как будто она использует среду определения или среду верхнего уровня, но определенно не текущую лексическую среду, для оценки символа 'a
, который является значением q
переменная. Переменная q
имеет четкую обязательную лексическую среду, созданную его let
форма - но при чем здесь символ 'a
Обязательный проживать? Откуда нам знать?
Подробности должны быть в документации.
Прежде всего, символ в кавычках - это такая же переменная, как и строка с теми же последовательностями символов, что и переменная в языке синтаксиса Си, таком как Javascript. У них нет ничего общего, так как они живут в разных мирах.
eval
не знает лексических переменных, только глобальные. Он знает о лексических переменных, которые находятся в структуре для оценки. Например.
(eval '(let ((tmp (list q q)))
tmp))
q
должен быть глобальным, но tmp
является лексической переменной
Стандартная схема, также известная как R6RS, использует второй аргумент, в котором вы можете выбрать, какие библиотеки должны быть доступны. Они все еще считаются глобальными.
Переменные связаны во время выполнения. Реализации свободны для оптимизации и постоянного сворачивания, если эта оптимизация не нарушает отчет.
eval
это мощная процедура, которая никогда не должна использоваться, если это не самый разумный способ решить проблему. Я видел это дважды в производственном коде за свою 17-летнюю карьеру, и я думаю, что это слишком много.