(pprint (meta #'+)) ;; #'+ is the + var
;; {:added "1.2",
;; :name +,
;; :file "clojure/core.clj",
;; :column 1,
;; :line 984,
;; :arglists ([] [x] [x y] [x y & more]),
;; ...
符号和集合支持元数据,一个关于符号或集合的数据映射。元数据系统允许对数据进行任意注释。它用于向编译器传达有关类型的信息,但也可以被应用程序开发人员用于多种目的,例如注释数据源、策略等。
关于元数据需要理解的一点是,它不被认为是对象值的一部分。因此,元数据不影响相等性(或哈希码)。只有元数据不同的两个对象是相等的。
也就是说,元数据及其与对象的关系是不可变的 - 具有不同元数据的对象是不同的对象。这样做的一个后果是,将元数据应用于延迟序列将实现序列的头部,以便两个对象可以共享同一个序列。
返回 obj 的元数据,如果没有元数据则返回 nil。
(pprint (meta #'+)) ;; #'+ is the + var
;; {:added "1.2",
;; :name +,
;; :file "clojure/core.clj",
;; :column 1,
;; :line 984,
;; :arglists ([] [x] [x y] [x y & more]),
;; ...
返回一个与 obj 类型和值相同的对象,其元数据为 map。
(def m ^:hi [1 2 3])
(meta (with-meta m {:bye true}))
;; {:bye true}
如果设置为逻辑真值,则在打印对象时,其元数据也将以读取器可以读取回的形式打印。
(def m ^:hi [1 2 3])
(binding [*print-meta* true]
(prn m))
;; ^{:hi true} [1 2 3]
返回一个与 obj 类型和值相同的对象,其元数据为 (apply f (meta obj) args)
。
(def m ^:hi [1 2 3])
(meta (vary-meta m merge {:bye true}))
;; {:hi true, :bye true}
除了 with-meta 之外,还有许多读取器宏(读取器:宏字符)用于在读取时将元数据应用于其后面的表达式
^{:doc "How it works!"}
- 将元数据映射添加到下一个读取的值的元数据中
^:dynamic
- 等同于 ^{:dynamic true}
^String
- 等同于 ^{:tag java.lang.String}
^"java.lang.String"
- 等同于 ^{:tag java.lang.String}
:tag
键用于提示 Clojure 编译器对象的类型。有关更多信息和特殊类型提示的完整列表,请参阅Java 交互:类型提示。
可以通过将元数据读取器宏链接在一起添加多个元数据片段。例如:^:dynamic ^ints obj
将同时将 :dynamic 标志和 ints 类型提示应用于 obj。元数据从右到左链接(左侧优先)。
请注意,元数据读取器宏是在读取时应用的,而不是在求值时应用的,并且只能与支持元数据的 value 一起使用,例如符号、var、集合、序列、命名空间、ref、atom、agent 等。一些重要的例外情况**不支持**元数据,例如字符串、数字、布尔值、Java 对象、关键字(这些对象被缓存并在运行时内共享)以及 deftype(除非它们显式地实现了 clojure.lang.IMeta)。