Подтвердить что ты не робот

Область переменной + eval в Clojure

В Clojure,

(def x 3)
(eval '(prn x))

печатает 3, тогда как

(let [y 3]
   (eval '(prn y)))

и

(binding [z 3] (eval '(prn z)))

сгенерировать исключение "Невозможно разрешить var".

В соответствии с http://clojure.org/evaluation, eval, load-string и т.д. генерируют временные пространства имен для оценки их содержимого. Поэтому я ожидал бы, что ни один из приведенных выше образцов кода не будет работать, поскольку (def x 3) выполняется в моем текущем пространстве имен, а не в файле, созданном eval.

  • Почему первый пример кода работает, а не последние два?
  • Как я могу eval создать форму со связанными переменными без использования def?

Спасибо!

4b9b3361

Ответ 1

1.:

Причина этого не срабатывает (более или менее) на странице, которую вы указали:

It is an error if there is no global var named by the symbol […]

и

[...]

  1. В текущем пространстве имен выполняется поиск, чтобы увидеть, есть ли отображение от символа до var. Если это так, значение - это значение привязки var, обозначаемый символом.

  2. Это ошибка.

eval оценивает формы в пустой (null в CL-lingo) лексической среде. Это означает, что вы не можете получить доступ к привязкам к лексической переменной из области вызова. Кроме того, binding создает новые привязки для существующих vars, поэтому вы не можете использовать его "самостоятельно", не имея declare d или def ed переменных, которые вы пытаетесь связать. Кроме того, лексические переменные (по крайней мере, в CL, но я был бы удивлен, если бы это было не так для Clojure) уже перестали существовать во время выполнения - они переводились на адреса или значения.

См. также мой более старый пост об этой теме.

2:.

Итак, вы должны использовать динамические переменные. Вы можете избежать явного def, но вам по крайней мере нужно declare их (какие def имена переменных без привязок):

user=> (declare x)
#'user/x
user=> (binding [x 10] (eval '(prn x)))
10
nil
Кстати: я полагаю, вы знаете, зачем вам нужно eval, и что его использование считается злым, когда другие решения будут уместны.