Форма eval должна оценивать данную форму в нулевой лексической среде, я не понимаю, что ожидаю

Скажем, у меня есть специальный var:

(defvar x 20)

то я делаю следующее:

(let ((x 1)) (eval '(+ x 1))

который оценивается в 2.

Согласно CLHS, eval "Оценивает форму в текущей динамической среде и нулевой лексической среде". Итак, я ожидаю получить 21 вместо 2.

Я что-то пропустил?

Теперь, если у меня нет динамической привязки для символа y, оценка

(let ((y 1)) (eval '(+ y 1))

Я получаю условие: "Переменная Y несвязана", что имеет смысл, поскольку для y нет динамической привязки.

Примечание. Я использую SBCL 1.0.57

Оцените свою помощь заранее!

Ответ 1

в вашем примере x есть special, что означает, что он связан в динамической среде

y не является особым, поэтому он связан в лексической среде


поэтому во время первого eval среды могут быть представлены следующим образом:

dynamic environment:  { x : 1 } -> { x : 20, ...other global variables... } -> nil
lexical environment:  nil

символ x является специальным, поэтому eval смотрит вверх x в текущую динамику окружающей среды и находит x = 1


Предполагая, что он был запущен в том же lisp как последний пример, среда вашего второго eval выглядит так:

dynamic environment: { x : 20,  ...other global variables... } -> nil
lexical environment: { y :  1 } -> nil

символ y не является особым, поэтому eval смотрит y в нулевом значении лексическая среда - не текущая лексическая среда - и ничего не находит.

это имеет смысл, когда вы понимаете, что lisp обычно скомпилирован, а лексический среда может быть оптимизирована до простых инструкций mov в некоторых случаях.

Ответ 2

DEFVAR объявляет свои переменные специальными. Во всем мире. Вы также можете легко удалить это.

Это также причина, по которой вы никогда не должны использовать общие имена, такие как x, i, list как имена переменных для DEFVAR. Убедитесь, что вместо этого вы используете *x*, *i* и *list*. В противном случае все переменные, даже локальные, с этими общими именами будут объявлены специальными.