Clojure's defrecord - how to use it?
我正在尝试使用Clojure中的
1 2 3 4 5 6 7 8 9 | (defrecord MyType [a b] (constructor [N] ; I'd like to build an initial instance, creating a and b as vectors of length N ) (mutate-and-return [] ; I'd like to mutate (assoc the vectors) and return the new structure, a and b modified ) ) |
我想先调用构造函数,然后再调用mutator(还有其他一些不可变的函数,但我不想让这个问题更复杂)。
或者,如果这不是惯用的Clojure,您应该如何做这样的事情?
定义记录的方法如下:
1 | (defrecord MyType [a b]) |
请注意,在Clojure中,通常不会在记录类型本身内定义"方法"(例外是如果您想直接实现Java接口或协议)。
免费自动生成一个基本构造函数(以
1 2 3 4 | (def foo (->MyType [1 2 3] [4 5 6])) foo => #user.MyType{:a [1 2 3], :b [4 5 6]} |
然后,您可以编写使用此功能的更复杂的构造函数,例如
1 2 3 4 5 6 7 | (defn mytype-with-length [n] (let [a (vec (range n)) b (vec (range n))] (->MyType a b))) (mytype-with-length 3) => #user.MyType{:a [0 1 2], :b [0 1 2]} |
而且"变异和返回"也是免费提供的-您可以使用asoc:
1 2 | (assoc foo :b [7 8 9]) => user.MyType{:a [1 2 3], :b [7 8 9]} |
Clojure defrecord示例:
;;定义地址记录
1 | (defrecord Address [city state]) |
;;定义人员记录
1 | (defrecord Person [firstname lastname ^Address address]) |
;;购买了构造函数
1 2 | (defn make-person ([fname lname city state] (->Person fname lname (->Address city state)))) |
;;创建一个人
1 | (def person1 (make-person"John""Doe""LA""CA")) |
;;检索值
1 2 | (:firstname person1) (:city (:address person1)) |