Ral*_*lph 10 constructor clojure
关注如何从一系列值中创建记录,如何编写defrecord构造函数调用并从a中分配字段Map,留下未命名的字段nil?
(defrecord MyRecord [f1 f2 f3])
(assign-from-map MyRecord {:f1 "Huey" :f2 "Dewey"}) ; returns a new MyRecord
Run Code Online (Sandbox Code Playgroud)
我想可以写一个宏来做这件事.
Mic*_*zyk 12
你可以简单地merge将地图写入用nils 初始化的记录:
(merge (MyRecord. nil nil nil) {:f1 "Huey" :f2 "Dewey"})
Run Code Online (Sandbox Code Playgroud)
请注意,记录能够以类似地图的方式保存存储在额外键下的值.
可以使用反射获取记录字段列表:
(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"})))
Run Code Online (Sandbox Code Playgroud)
后一个函数返回一系列字符串:
user> (get-record-field-names MyRecord)
("f1" "f2" "f3")
Run Code Online (Sandbox Code Playgroud)
__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))))
Run Code Online (Sandbox Code Playgroud)
并使用它来创建记录类的空实例,如下所示:
user> (empty-record user.MyRecord)
#:user.MyRecord{:f1 nil, :f2 nil, :f3 nil}
Run Code Online (Sandbox Code Playgroud)
完全限定名称在这里至关重要.只要empty-record在编辑引用它的任何表单时声明了记录类,它就会起作用.
如果把empty-record它写成函数,那么可以让它期望一个实际的类作为参数(避免"完全限定"的问题 - 你可以在给定的上下文中以任何方式命名你的类),尽管代价是在运行时进行反射.
小智 5
如今,当定义记录时, Clojure 会生成一个map->RecordType函数。
(defrecord Person [first-name last-name])
(def p1 (map->Person {:first-name "Rich" :last-name "Hickey"}))
Run Code Online (Sandbox Code Playgroud)
映射不需要定义记录定义中的所有字段,在这种情况下,缺少的键在结果中具有 nil 值。映射还允许包含不属于记录定义的额外字段。
| 归档时间: |
|
| 查看次数: |
3500 次 |
| 最近记录: |