请考虑 (defn f ^{:foo "bar"} [x] (* x x)) and (defn g #^{:foo "bar"} [x] (* x x)) 编译和运行都可以。 我有两个问题:首先,为什么(meta f)和(meta g)只产生nil?我本来期望它们会产生{:foo "bar"};也就是说,我的元数据定义可能有误吗? 其次,这两种元数据语法有什么区别?第二种看起来像是一个“标记文字”,与edn扩展数据符号有关,但如果没有更多上下文或示例,我无法理解它。
在Clojure 1.2中,#^元数据读取宏已被替换为^。虽然目前两者没有区别,但旧形式已被弃用,您应该专门使用^。元数据文字应该在要附加到的项之前。(defn ^{:foo "bar"} f [x] (* x x)) 还需要记住的一件事是,上述定义中的元数据不是附加在函数上的,而是附加在引用该函数的var上的。您可以使用以下代码获取f var的元数据: (meta (var f)) 或者使用 var 读取宏: (meta #'f)
(doc defn)
,它说名称应该在元数据之前,除非我误读了文档:"clojure.core/defn([name doc-string? attr-map? [params*] prepost-map? body] [name doc-string? attr-map? ([params*] prepost-map? body) + attr-map?])" - Reb.Cabinattr-map
是defn
宏的一个特殊功能,旨在使将元数据附加到正在定义的变量更容易。当使用attr-map
时,不应该在map前面加上^
((defn f {:foo "bar"} [] :baz)
)。我实际上没有看到过这种用法,使用^
读取宏更为常见。我猜attr-map
在较早版本的Clojure中很有用,当时处理元数据比较困难,但现在使用^{:foo "bar}
形式更符合惯用法,而且更通用(可以放在任何可以保存元数据的对象之前)。 - mtyaka