不能 change/establish 的根绑定:[some-def] 与 Clojure 中的 set
Can't change/establish root binding of: [some-def] with set in 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's var -> *warn-on-reflection*
)
(set! *warn-on-reflection* true)
=> true
*warn-on-reflection*
=> true
(set! *warn-on-reflection* false)
=> false
*warn-on-reflection*
=> false
动态变量只能 set!
在 binding
范围内。因此,仅在 *pop*
上调用 set!
是行不通的 - 您需要在上面调用堆栈中某处绑定的运行时动态范围内。
(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)
请注意,"dynamic scope" 部分意味着在 binding
中,您可以进行任意嵌套调用,并且仍然可以设置和读取 [=14= 的 per-thread 值].
关于 *warn-on-reflection*
,这看起来像是特殊行为,但实际上完全一样,除了隐藏在视图之外。 REPL 本身围绕每个 REPL 语句的 eval 创建了一个动态绑定范围,并绑定了一组 hard-coded 动态变量,其中 *warn-on-reflection*
是一个。您可以找到那组绑定 here.
您可以使用 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
我无法将动态变量的值设置为新值。
(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's var -> *warn-on-reflection*
)
(set! *warn-on-reflection* true)
=> true
*warn-on-reflection*
=> true
(set! *warn-on-reflection* false)
=> false
*warn-on-reflection*
=> false
动态变量只能 set!
在 binding
范围内。因此,仅在 *pop*
上调用 set!
是行不通的 - 您需要在上面调用堆栈中某处绑定的运行时动态范围内。
(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)
请注意,"dynamic scope" 部分意味着在 binding
中,您可以进行任意嵌套调用,并且仍然可以设置和读取 [=14= 的 per-thread 值].
关于 *warn-on-reflection*
,这看起来像是特殊行为,但实际上完全一样,除了隐藏在视图之外。 REPL 本身围绕每个 REPL 语句的 eval 创建了一个动态绑定范围,并绑定了一组 hard-coded 动态变量,其中 *warn-on-reflection*
是一个。您可以找到那组绑定 here.
您可以使用 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