【问题标题】:Disconnect between :dynamic metadata and actually-dynamic Vars in ClojureClojure 中:动态元数据和实际动态变量之间的断开连接
【发布时间】: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


【解决方案1】:

您在没有元数据的情况下识别出的动态变量是在 Java 运行时中创建的(请参阅从第 180 行开始的RT.java)。在引导程序使def 可用(即在 core.clj 和 core_print.clj 中)之后,其他的在 Clojure 中创建。

元数据可以稍后添加,在某些情况下是(例如*agent* 有一个文档字符串),所以这不是一个完整的答案。正如您所指出的那样,我可以推测缺乏实际重要性使得调整引导中使用的变量的元数据成为低优先级。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-07
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-28
    • 2021-04-30
    相关资源
    最近更新 更多