gpt4 book ai didi

clojure - 为什么我可以设置!内置动态(?)Clojure 变量?

转载 作者:行者123 更新时间:2023-12-02 14:56:50 25 4
gpt4 key购买 nike

为什么我能做到这一点:

> (set! *unchecked-math* true)
true
> (set! *warn-on-reflection* false)
false

但不能这样做:

> (def ^:dynamic *x*)
#'user/*x*
> (set! *x* 1) ;; no luck, exception!

最佳答案

运行时是否可能将内置动态隐式包装在绑定(bind)形式中?因为这有效,例如:

user=> (def ^:dynamic *x*)
user=> (binding [*x* false] (set! *x* true))
true
user=>

需要注意的一件事是,文档明确指出尝试通过 set! 修改根绑定(bind)是错误的,请参阅:

http://clojure.org/reference/vars

内置函数也可能被特殊对待,例如,如果您查看 x 的元数据:

user=> (meta #'*x*)
{:dynamic true, :line 1, :column 1, :file "/private/var/folders/8j/ckhdsww161xdwy3cfddjd01d25k_1q/T/form-init5379741350621280680.clj", :name *x*, :ns #object[clojure.lang.Namespace 0x6b8f00 "user"]}

它被标记为动态,而 *warn-on-reflection* 未标记为动态,但仍以绑定(bind)形式工作:

user=> (meta #'*warn-on-reflection*)
{:added "1.0", :ns #object[clojure.lang.Namespace 0x377fc927 "clojure.core"], :name *warn-on-reflection*, :doc "When set to true, the compiler will emit warnings when reflection is\n needed to resolve Java method calls or field accesses.\n\n Defaults to false."}
user=> (binding [*warn-on-reflection* true] (set! *warn-on-reflection* false))
false
user=>

这大概是为了向后兼容,因为在早期版本的 clojure 中,带有耳罩(每侧都有星星)的变量按照惯例是动态的。但无论如何,这只是表明内置函数的处理方式略有不同。

现在,我决定更进一步,grep clojure 的源代码,寻找 warn-on-reflection,这让我找到了常量WARN_ON_REFLECTION,这让我在 RT.java 中看到这样的代码行:

https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L467

Var.pushThreadBindings(
RT.mapUniqueKeys(CURRENT_NS, CURRENT_NS.deref(),
WARN_ON_REFLECTION, WARN_ON_REFLECTION.deref()
,RT.UNCHECKED_MATH, RT.UNCHECKED_MATH.deref()));

这让我相信我最初的假设是正确的,某些特殊的全局变量隐式地包装在线程本地绑定(bind)中。

编辑:

正如评论中提到的,您可以使用 clojure.core/push-thread-bindings,但请务必遵循文档的建议,并使用 包裹在 try/catch/finally 中>pop-thread-bindings 在finally block 中。那时,您只需重新实现 binding (例如,在 repl 上运行 (source binding) ),这可能就是文档明确警告 的原因Push-thread-Bings 是一个低级函数,应该首选 Binding

关于clojure - 为什么我可以设置!内置动态(?)Clojure 变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38877341/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com