【发布时间】:2013-08-13 03:04:49
【问题描述】:
我正在学习 Clojure,并且正在使用动态范围。我发现了一些事情:
- 将
{:dynamic true}元数据添加到现有Var 实际上不会使Var 动态化。我可以理解您为什么希望这样,但这可能会产生误导。 - 您可以使用
(.isDynamic #'whatever)查看 Var 是否实际上是动态的 - 您可以(但可能不应该?)使用
(.setDynamic #'whatever)更改 Var 是否是动态的
简而言之,Var 的动态特性似乎存储在 clojure.lang.Var 类本身的内部,而将 ^:dynamic 元数据设置仅在默认时间会影响这一点内部状态。之后更改元数据似乎不会影响它。好的,好的。
我在查看命名空间 clojure.core 中的动态变量时发现了这一点。我检查了该命名空间中的哪些 Vars 设置了 :dynamic 元数据:
user=> (def metadyn (map key (filter #(-> % key resolve meta :dynamic) (ns-publics 'clojure.core))))
#'user/metadyn
user=> metadyn
(*3 *2 *print-level* *data-readers* *e *print-length* *1 *verbose-defrecords*
*clojure-version* *default-data-reader-fn* pr)
比我预期的要少,缺少像 *out* 和 *in* 这样的东西。
我检查了 Vars 实际上是什么是动态的:
user=> (def realdyn (map key (filter #(-> % key resolve .isDynamic) (ns-publics 'clojure.core))))
#'user/realdyn
user=> realdyn
(*compile-path* *3 *2 *ns* *print-level* *allow-unresolved-vars* *data-readers*
*unchecked-math* *math-context* *read-eval* *compile-files* *command-line-args*
*warn-on-reflection* *e *flush-on-newline* *out* *print-length* *1 *file* *verbose-defrecords*
*clojure-version* *use-context-classloader* *err* *default-data-reader-fn* *agent* pr
*print-dup* *print-readably* *fn-loader* *print-meta* *in* *source-path* *compiler-options* *assert*)
还有很多。
因此,以下 Var 是动态的,但并未声称在其元数据中:
user=> (clojure.set/difference (set realdyn) (set metadyn))
#{*compile-path* *ns* *allow-unresolved-vars* *unchecked-math* *math-context* *read-eval*
*compile-files* *command-line-args* *warn-on-reflection* *flush-on-newline* *out* *file*
*use-context-classloader* *err* *agent* *print-dup* *print-readably* *fn-loader* *print-meta*
*in* *source-path* *compiler-options* *assert*}
我的问题很简单:这有什么意义吗,我错过了什么?或者,这只是 Clojure 实现中记录草率的一个案例?
这个没有实际用处;只是想了解一下。
【问题讨论】:
-
它们是在 def 可用之前在运行时创建的。
-
谢谢,对我来说已经足够了。如果你把它放在回复中,我会把它标记为答案。
标签: clojure