元数据(Metadata)
今天接触到了clojure中的元数据,觉得有必要记录一下相关的概念,我的第一篇关于clojure的文章就从这里说起吧。
元数据(Metadata),用的最多的应该是在数据仓库领域,因为它被定义成“一种描述数据的数据”,我的第一感觉就是元数据就是数据的属性,是一组刻画具体数据的数据。就拿我们人来说,我们的身高,体重,胸围,肤色,发型,以及相貌等等就构成了属于我们的元数据。元数据被广泛的应用在各个领域,我觉得可以简单的理解成,我们人为的把数据分为两类:数据和属性数据。恩,元数据说来说去还是数据。
在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是构建在JVM之上的lisp方言,第1至4行创建了一个结构体,用来表示扑克牌中的梅花K,之后就两个对象进行了比较运算,在clojure中是用==和=来解决Equality中的歧义,接下来的两行就为card2添加了一个名为bent,值为true的元数据,在clojure中有两种方式添加元数据:预编译时(我个人对于read-time的理解)和运行时,{:bent true}很明显表示一个Map结构。#这个宏在clojure中有很多的用途,这里就是将{:bent true}这个Map分派给card2这个对象。#还可以用来表示Set,匿名函数和正则表达式。同样也有两种方式得到对象的元数据:
(meta object)
^object
最后的三行表明,元数据不会影响对象间的Equality。