ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## 元数据 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` 元数据是一个Boolean值表示这个函数是否是一个测试函数。 `:tag` 是一个字符串类型的类名或者一个 `Class` 对象,表示一个Var在Java里面对应的类型,或者一个函数的返回值。这些被称为“类型提示” 。提供这些可以提高代码性能。如果你想查看你的clojure代码里面哪里使用反射来决定类型信息 -- 也就是说这里可能会有性能的问题, 那么你可以设置全局变量 `*warn-on-reflection*` 为 `true` 。 一些元数据会由Clojure的编译器自动地绑定到Var对象。 `:file` 是定义这个 Var的文件的名字。 `:line` 是定义这个Var的行数。 `:name` 是一个Var的名字的 `Symbol` 对象。 `:ns` 是一个 `Namespace` 对象描述这个Var所在的名字空间。 `:macro` 是一个标识符标识这个符号是不是一个宏。 `:arglist` 是一个装有一堆vector的一个list, 表示一个函数所接受的所有的参数列表(前面在介绍函数的时候说过一个函数可以接受多个参数列表)。 函数以及宏,都是有一个 `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.repl包里面的 `source` 函数, 利用元数据来获取一个指定函数的源代码,比如: ``` (source reverse) ``` 上面代码的输出应该是: ``` (defn reverse "Returns a seq of the items in coll in reverse order. Not lazy." [coll] (reduce conj nil coll)) ```