您可以简单地将merge 映射到使用nils 初始化的记录中:
(merge (MyRecord. nil nil nil) {:f1 "Huey" :f2 "Dewey"})
请注意,记录能够以类似映射的方式保存存储在额外键下的值。
可以使用反射获取记录的字段列表:
(defn static? [field]
(java.lang.reflect.Modifier/isStatic
(.getModifiers field)))
(defn get-record-field-names [record]
(->> record
.getDeclaredFields
(remove static?)
(map #(.getName %))
(remove #{"__meta" "__extmap"})))
后一个函数返回一个字符串序列:
user> (get-record-field-names MyRecord)
("f1" "f2" "f3")
__meta 和 __extmap 分别是 Clojure 记录用来保存元数据和支持地图功能的字段。
你可以写类似的东西
(defmacro empty-record [record]
(let [klass (Class/forName (name record))
field-count (count (get-record-field-names klass))]
`(new ~klass ~@(repeat field-count nil))))
并使用它来创建记录类的空实例,如下所示:
user> (empty-record user.MyRecord)
#:user.MyRecord{:f1 nil, :f2 nil, :f3 nil}
完全限定名称在这里是必不可少的。只要在任何引用它的empty-record 表单被编译时声明了记录类,它就可以工作。
如果 empty-record 被写成一个函数,人们可以让它期望一个实际的类作为参数(避免“完全限定”问题——你可以在给定的上下文中以任何方便的方式命名你的类) ,但代价是在运行时进行反射。