[英]Clojure: How to Hook into Defrecord Constructor
The title of this question may over specify the implementation, but the idea is simple, I want to create and a record, or something similar, it could be a map a type declared by deftype, etc... I want to create the object with a string id and an int age, but I want to convert the id to a UUID and the age to an int if it is not already. 这个问题的标题可能过度指定了实现,但是这个想法很简单,我想创建一个记录,或者类似的东西,它可以是一个由deftype声明的类型的映射,等等...我想创建对象带有字符串id和int age,但是我想将id转换为UUID,如果不是,则将age转换为int。 How do I do this idiomatically? 我该怎么习惯?
So far I have something like this: 到目前为止,我有这样的事情:
(let [item (my.model/map->Item {
:id (UUID/fromString "62c36092-82a1-3a00-93d1-46196ee77204")
:age (int 6)})])
But I dont want to do both of those operations every time I create an item, I want that logic in 1 place. 但是我不想每次创建一个项目时都要做这两个操作,我希望将逻辑放在1个地方。 I could make an auxiliary function to do this, but is there built in support for this in deftype or defrecord? 我可以做一个辅助功能来做到这一点,但是在deftype或defrecord中是否对此有内置支持?
It's easiest to use a function that takes your input map and constructs your Item from that. 使用获取输入映射并从中构造Item的函数最简单。
(defn make-item
[{:keys [id age] :as input}]
{:pre [(string? id)
(number? age)]}
(-> input
(update-in [:id] #(UUID/fromString %))
(update-in [:age] int)
my.model/map->Item))
This will scale nicely as you need more keys or stricter constraints, and adapts to other record types. 当您需要更多键或更严格的约束时,这将很好地扩展,并适应其他记录类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.