断开:Clojure中的动态元数据和实际动态Vars

时间:2013-08-11 20:12:26

标签: clojure

我正在学习Clojure并且正在玩动态范围。我发现了一些事情:

  • 向现有Var添加{:dynamic true}元数据实际上并不会使Var动态化。我可以理解你为什么要这样,但这可能会产生误导。
  • 您可以使用(.isDynamic #'whatever)
  • 查看Var是否真的具有动态效果
  • 您可以(但可能不应该?)通过(.setDynamic #'whatever)
  • 更改Var是否为动态

简而言之,看起来Var的动态特性存储在clojure.lang.Var类本身的内容中,并且仅在def时间设置^: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*)

还有更多。

因此,以下Vars是动态的,但声称不在其元数据中:

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实施中草率记账的情况吗?

没有实际用途;只是想了解。

1 个答案:

答案 0 :(得分:1)

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

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