Clojure:当我重新输入定义时,为什么函数的元数据会发生变化?

时间:2011-12-09 21:30:59

标签: clojure metadata

像这样:

java -cp clojure.jar clojure.main
Clojure 1.2.0
user=> (defn f [x] x)
#'user/f
user=> (meta f)
{:ns #<Namespace user>, :name f}
user=> (defn f [x] x)
#'user/f
user=> (meta f)
{:ns #<Namespace user>, :name f, :file "NO_SOURCE_PATH", :line 1, :arglists ([x])}
user=> 

为什么对meta的调用每次都不会返回相同的值?

更新:通过再玩一些,我能够得到我当前问题的答案。 defn宏扩展为将(meta (var f)添加到f元数据的表单。当(meta (var f)第一次定义时,(meta f)包含f中的额外信息。所以现在我的问题变成了,defn为什么这样实现?

java -cp clojure.jar clojure.main
Clojure 1.2.0
user=> (defn f [x] x)
#'user/f
user=> (meta f)
{:ns #<Namespace user>, :name f}
user=> (meta (var f))
{:ns #<Namespace user>, :name f, :file "NO_SOURCE_PATH", :line 1, :arglists ([x])}
user=> (macroexpand '(defn f [x] x))
(def f (.withMeta (clojure.core/fn f ([x] x)) (.meta (var f)))) ; (.meta x) seems to be the same as (meta x)
user=> 

2 个答案:

答案 0 :(得分:1)

显然,这种行为在Clojure 1.2中或多或少是“偶然的”,并且在1.3中已经改变: http://groups.google.com/group/clojure/browse_thread/thread/964bba0ead8218ee/3ef0c841474c85f4?lnk=gst&q=function+meta+data#3ef0c841474c85f4

在1.3中,只有Var包含元数据 - 函数本身未按defn分配任何元数据。

答案 1 :(得分:0)

Clojure使用元数据来存储从中读取函数的信息,文档等。重新定义函数可以改变它。


来自http://clojure.org/metadata

  

理解元数据的一个重要事项是它不被视为对象价值的一部分。因此,元数据不会影响相等(或哈希码)。仅在元数据方面不同的两个对象是相同的。

另一种看待这种情况的方法是考虑相反的情况:假设Clojure没有重置元数据。

(defn fun []
  "docs for the original function"
  ...)

然后重新定义它:

(defn fun []
   ;; no doc string, different body
   ...)

如果不重置元数据(doc fun),则会显示“原始函数的文档”。

最后,vars的重新定义通常在开发期间完成,通常不在程序的正常执行中。因此,完全重新定义它而不是保留以前定义中的内容是有意义的。