本文参考自http://java.ociweb.com/mark/clojure/article.html#Metadata
也许你在别的计算机语言中见过元数据这一概念,但Clojure中的元数据,也即Metadata有其独有的含义。Clojure里面的Metadata是附加到一个符号或者集合上的一些数据,它们和符号或者集合的逻辑数据没有直接的关系。两个逻辑上一样的方法可以有不同的元数据。比如两张扑克牌都是梅花K,Metadata是用于指示那张牌是横向着的,事实上对于大多数扑克牌游戏,扑克牌的倾斜与否对扑克牌所表示数值根本没有影响。如下图所示:
(defstruct card-struct :rank :suit)
(def card1 (struct card-struct :king :club))
(def card2 (struct card-struct :king :club))
(println (== card1 card2)) ; same identity? -> false
(println (= card1 card2)) ; same value? -> true
(def card2 #^{:bent true} card2) ; adds metadata at read-time
(def card2 (with-meta card2 {:bent true})) ; adds metadata at run-time
(println (meta card1)) ; -> nil
(println (meta card2)) ; -> {:bent true}
(println (= card1 card2)) ; still same value despite metadata diff. -> true
在clojure中有些元数据有特定的用途。:private有一个boolean值,用于指示在定义某个Var对象的Namespace中是否
访问受限。:doc则是一个Var对象的文档字符串。:test则有一个用于指示一个不接受外部参数的函数是否为一个测试函
数。:tag是一个String类型的类名或者一个Class 对象,表示一个Var在Java里面对应的类型,抑或是一个函数的返回类
型。这些都是被作为类型提示。提供这些元数据能够提高性能。
如果你想查看你的clojure代码里面哪里使用反射来决定类型信息 -- 也就是说这里可能会有性能的问题, 那么你可以设置
全局变量*warn-on-reflection* 为true。
Clojure编译器会自动将某些元素附加到Var对象上。
:file是定义Var对象的那个文件的字符串名称。:line则是文件中定义Var对象所在的行数。:name是给Var对象提供名称的一
个Symbol。:ns是一个Namespace对象,描述了定义Var对象的Namespace。:macro则是一个指示Var对象是一个宏而非函
数或者绑定变量。:arglist是一序列向量,每个向量都描述了一个函数所能够接受的参数名称。记住,一个函数可以有多个参
数列表和函数体。函数或者宏都是由一个Var对象来表示,有各自相关联的元数据。
例如在REPL环境中输入 (meta (var reverse)),输出内容将如下所述,只是都在同一行而已:
{
:ns #<Namespace clojure.core>,
:name reverse,
:file "core.clj",
:line 630,
:arglists ([coll]),
:doc "Returns a seq of the items in coll in reverse order. Not lazy."
}
(defn reverse
"Returns a seq of the items in coll in reverse order. Not lazy."
[coll]
(reduce conj nil coll))
本文介绍了Clojure中的元数据概念及其应用。元数据是附加到符号或集合上的数据,与逻辑数据分离。文章通过示例解释了如何在读取和运行时添加元数据,并讨论了特定元数据如:private、:doc、:test等的作用。
242

被折叠的 条评论
为什么被折叠?



