?原帖地址:http://java.ociweb.com/mark/clojure/article.html#Metadata
?作者:R. Mark Volkmann
?译者:RoySong
?
??? Clojure的元数据是附属于符号或者集合的数据,而没有具体的逻辑值。两个对象在逻辑上相同,就像扑克中的两张
王相同,能够拥有不同的元数据。举个例子,元数据能够用来指明某张扑克是否是弯的。而对于大部分扑克游戏来说,
事实上扑克是否是弯的完全跟扑克的价值无关:
(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
有一个布尔值来指明某个Var的
访问
权限是否被限制在它被定义的
命名空间中。 :doc是显示出某个Var的文档字符串。
:test拥有一个布尔值来指明某个无参函数是否测试函数。
?
??? :tag是一个字符串类名,或者描述某个Var的java类型的类对象,或者一个函数的返回类型。这些被称为“类型提示”(
"type hints"),使用类型提示能够提升性能。为了看到你的程序中什么地方Clojure采用了反射来识别类型,来作为性能
提升点,应该将全局变量*warn-on-reflection*设为true。
?
??? 某些元数据会被Clojure编译器自动绑定到Var上。:file是用来定义Var的文件字符串名。
:line是文件中Var被定义地方
的整型行数。 :name是为Var提供名字的一个符号。
:ns是一个命名空间对象用来描述Var被定义的命名空间。
:macro是个
布尔值用来指明Var是个与函数相反的宏或者绑定。 :arglist是一个Vector的列表,其中每个vector都包含了一个函数接受
的所有参数的名字。回想一下,函数是可以拥有不止一组参数和函数体的。
?
??? 函数和宏,都表现为一个Var对象的形式,拥有其关联的元数据。举个例子,在REPL中输入:(meta (var reverse))或者
^#'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." }?
??? Clojure Contrib
中repl-utils库里(clojure.contrib.repl-utils命名空间中
)的source函数,能够采用这些元数据来
检索指定函数或者宏的源代码,例子如下:
(source reverse)
?
??? 执行后产生以下输出:
(defn reverse "Returns a seq of the items in coll in reverse order. Not lazy." [coll] (reduce conj nil coll))
?
译者注:
元数据的概念,来源于百度百科:
元数据(Metadata)是描述其它数据的数据(data about other data),或者说是用于提供某种资源的有关信息的结构数据(structured data)。元数据是描述信息资源或数据等对象的数据,其使用目的在于:识别资源;评价资源;追踪资源在使用过程中的变化;实现简单高效地管理大量网络化 数据;实现信息资源的有效发现、查找、一体化组织和对使用资源的有效管理。