Невозможно изменить / установить привязку корня из: [some-def] с установленным в Clojure
Я не мог установить значение моей динамической переменной на новое.
(def *pop* true)
(set! *pop* false)
=> IllegalStateException Can't change/establish root binding of: *pop* with set clojure.lang.Var.set (Var.java:221)
Также я добавил ^:dynamic
, который тоже не работал.
(def ^:dynamic *pop* true)
(set! *pop* false)
=> IllegalStateException Can't change/establish root binding of: *pop* with set clojure.lang.Var.set (Var.java:221)
Но, с другой стороны, этот код работает,(clojure core var -> *warn-on-reflection*
)
(set! *warn-on-reflection* true)
=> true
*warn-on-reflection*
=> true
(set! *warn-on-reflection* false)
=> false
*warn-on-reflection*
=> false
2 ответа
Динамические переменные могут быть только set!
внутри binding
объем. Так что просто звоню set!
на *pop*
не будет работать - вы должны находиться в динамической области привязки привязки где-то в стеке вызовов выше.
(def ^:dynamic *pop* true)
(binding [*pop* *pop*] ;; defaulted to the root binding value
(set! *pop* false) ;; ok, because in dynamic binding scope
(println *pop*)) ;; prints "false" (inside per-thread dynamic binding)
(println *pop*) ;; prints "true" (root value)
Обратите внимание, что часть "динамического объема" означает, что в binding
вы можете делать произвольные вложенные вызовы и при этом иметь доступ к установке и чтению значения для потока *pop*
,
относительно *warn-on-reflection*
Это выглядит как особое поведение, но на самом деле оно точно такое же, за исключением скрытого от глаз. Сам REPL создает динамическую область привязки вокруг eval каждого оператора REPL с привязками для жестко запрограммированного набора динамических переменных, из которых *warn-on-reflection*
это один. Вы можете найти этот набор привязок здесь.
Вы можете использовать alter-var-root для изменения корневых переменных.
user=> (def *pop* true)
Warning: *pop* not declared dynamic ...
#'user/*pop*
user=> (alter-var-root #'*pop* (constantly false))
false
user=> *pop*
false