首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Clojure的defrecord -如何使用它?

Clojure的defrecord -如何使用它?
EN

Stack Overflow用户
提问于 2012-08-15 01:57:21
回答 3查看 15.2K关注 0票数 24

我正在尝试用Clojure中的defrecord创建我自己的不可变数据类型/方法。我们的目标是有一个数据类型,我可以创建它的实例,然后调用它的方法来返回带有变异变量的自身的新副本。假设a和b是向量。我想在两者中更新一个值,并返回整个结构的一个新副本,其中包含更新后的向量。这显然不能编译,我只是想让大家理解我的想法。

代码语言:javascript
复制
(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
  )
)

我想调用构造函数,然后调用赋值函数(还有其他函数不会发生变化,但我不想让这个问题变得更复杂)。

或者,如果这不是惯用的Clojure,那么您应该如何做这样的事情?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-08-15 02:21:16

下面是你如何定义你的记录:

代码语言:javascript
复制
(defrecord MyType [a b])

请注意,在Clojure中,您通常不会在记录类型本身中定义“方法”(例外情况是您希望直接实现Java接口或协议)。

免费自动生成一个基本构造函数(以->为前缀):

代码语言:javascript
复制
(def foo (->MyType [1 2 3] [4 5 6]))

foo
=> #user.MyType{:a [1 2 3], :b [4 5 6]}

然后,您可以编写更复杂的构造函数来使用它,例如

代码语言:javascript
复制
(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]}

而且“变异和返回”也是免费的--你可以只使用assoc

代码语言:javascript
复制
(assoc foo :b [7 8 9])
=> user.MyType{:a [1 2 3], :b [7 8 9]}
票数 36
EN

Stack Overflow用户

发布于 2017-11-11 17:20:41

Clojure defrecord示例:

;;定义地址记录

代码语言:javascript
复制
(defrecord Address [city state])

;;定义人员记录

代码语言:javascript
复制
(defrecord Person [firstname lastname ^Address address])

;;构建构造函数

代码语言:javascript
复制
(defn make-person ([fname lname city state]
               (->Person fname lname (->Address city state))))

;;创建一个人

代码语言:javascript
复制
(def person1 (make-person "John" "Doe" "LA" "CA"))

;;检索值

代码语言:javascript
复制
(:firstname person1)
(:city (:address person1))
票数 9
EN

Stack Overflow用户

发布于 2020-12-10 21:43:29

Clojure允许您创建记录,这些记录是自定义的maplike数据类型。它们类似于maplike,因为它们将键与值相关联,您可以像使用map一样查找它们的值,并且它们像map一样是不可变的。

代码语言:javascript
复制
(defrecord Person [last first address])
;=> core.Person

(defrecord Ad [street city zip])
;=> core.Ad

(def p1 (Person. "Jhon" "Mick"
                 (Ad. "US187956" "NY" 3369)))
;=> #'core/p1

(update-in p1 [:address :zip] inc)
;=> #core.Person{:last "Jhon", :first "Mick", :address #playsync.core.Ad{:street "US187956", :city "NY", :zip 3370}}

(assoc p1 :last "Adam")
;=> #core.Person{:last "Adam", :first "Mick", :address #playsync.core.Ad{:street "US187956", :city "NY", :zip 3370}}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11958027

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档