我正在学习Clojure并且正在玩动态范围。我发现了一些事情:
{:dynamic true}
元数据实际上并不会使Var动态化。我可以理解你为什么要这样,但这可能会产生误导。(.isDynamic #'whatever)
(.setDynamic #'whatever)
简而言之,看起来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实施中草率记账的情况吗?
没有实际用途;只是想了解。
答案 0 :(得分:1)
您在没有元数据的情况下识别的动态变量是在Java运行时中创建的变量(参见RT.java从第180行开始)。其他是在引导使def
可用(即在core.clj和core_print.clj中)之后在Clojure中创建的。
元数据可能稍后添加,在某些情况下(例如*agent*
有文档字符串),所以这不是一个完整的答案。我可以推测,正如你所指出的那样,缺乏实际重要性,已经完成了引导低优先级的变量的元数据。