clojure - 如何让核心 clojure 函数与我的 defrecords 一起工作

标签 clojure protocols frequency census

我有一个叫做 bag 的 defrecord。它的行为类似于要计数的项目列表。这有时称为频率或普查。我希望能够执行以下操作

(def b (bag/create [:k 1 :k2 3])  
(keys bag)
=> (:k :k1)

我尝试了以下方法:

(defrecord MapBag [state]                                                                                                                                         
  Bag                                                                                                                                                             
   (put-n [self item n]                                                                                                                                          
     (let [new-n (+ n (count self item))]                                                                                                                        
          (MapBag. (assoc state item new-n))))                                                                                                                      

  ;... some stuff

  java.util.Map                                                                                                                                                   
    (getKeys [self] (keys state)) ;TODO TEST                                                                                                                      

  Object                                                                                                                                                          
   (toString [self]                                                                                                                                              
     (str ("Bag: " (:state self)))))   

当我尝试在 repl 中要求它时,我得到:

java.lang.ClassFormatError: Duplicate interface name in class file compile__stub/techne/bag/MapBag (bag.clj:12)

这是怎么回事?如何在我的包上获得 key 功能?另外,我是否通过假设 clojure 的 keys 函数最终在作为其参数的 map 上调用 getKeys 来以正确的方式解决这个问题?

最佳答案

Defrecord 自动确保它定义的任何记录参与 ipersistentmap 接口(interface)。因此,您无需任何操作

即可在其上调用键。

所以你可以定义一个记录,并像这样实例化和调用键:

user> (defrecord rec [k1 k2])
user.rec
user> (def a-rec (rec. 1 2))
#'user/a-rec
user> (keys a-rec)
(:k1 :k2)

您的错误消息表明您的一个声明正在复制 defrecord 免费提供给您的接口(interface)。我认为实际上可能两者兼而有之。

是否有某些原因导致您不能只使用普通 map 来满足您的目的?对于 Clojure,您通常希望尽可能使用普通数据结构。

编辑:如果出于某种原因您不想包含 ipersistentmap,请查看 deftype。

关于clojure - 如何让核心 clojure 函数与我的 defrecords 一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3744349/

相关文章:

clojure - 在 Clojure 中是否有一种简单的方法可以在列表类型之间进行转换?

objective-c - 将协议(protocol)作为方法参数传递

swift - 在使用协议(protocol)转换访问计算变量期间调用结构体

Python - 如何按频率检查数字组合

MySQL 按组最频繁的 SELECT

android - 如何以16位格式分别在左右声道上播放两个正弦波?

clojure - 我们如何测试某物是否是引用?

logging - 如何决定哪些附加程序对 `clojure.tools.logging` 的日志进行操作?

java - android 上 java 的替代品

java - Google Protocol 重复值的结构是怎样的?它们的局限性和优势是什么?