Clojure值相等与集合

Clojure值相等与集合,clojure,set,Clojure,Set,如果我有一个自定义类型,并使用它创建两个具有完全相同值的独立实例,那么我可以使用什么方法来确定这两个对象是等效的相同?和=和=似乎不起作用。我本以为会有一些设置类型比较的协议。归根结底,我希望这样做,就不可能在一个集合中添加相同的东西 (deftype Ref [id]) (def r1 (->Ref 1)) (def r2 (->Ref 1)) (= r1 r2) ;false rather than true (def refs #{}) (conj refs r1 r2) ;a

如果我有一个自定义类型,并使用它创建两个具有完全相同值的独立实例,那么我可以使用什么方法来确定这两个对象是等效的<代码>相同?和
=
=
似乎不起作用。我本以为会有一些设置类型比较的协议。归根结底,我希望这样做,就不可能在一个集合中添加相同的东西

(deftype Ref [id])
(def r1 (->Ref 1))
(def r2 (->Ref 1))
(= r1 r2) ;false rather than true
(def refs #{})
(conj refs r1 r2) ;adds both, but want one

=
defrecord
一起工作,但是我如何定义
=
=
定义
deftype

defrecord
已经有了您描述的行为:

user=> (defrecord Point [x y])
user.Point
user=> (= (Point. 0 0) (Point. 0 0))
true
user=> (into #{} [(Point. 0 0) (Point. 1 1) (Point. 0 0)])
#{#user.Point{:x 1, :y 1} #user.Point{:x 0, :y 0}}
另一方面,
deftype
默认情况下不实现Clojure通常的结构相等(也不实现
deftstruct
提供的可读打印方法):


在deftype中,扩展
对象
并实现
等于
,以赋予它们相等语义:

(deftype Ref [id]
  Object
  (equals [_ other] (= id (.id other))))
集合包含还需要哈希代码支持:

(deftype Ref [id]
  Object
  (equals [_ other] (= id (.id other)))
  (hashCode [_] id) 
  clojure.lang.IHashEq 
  (hasheq [_] id))

我在那里实现了Java哈希支持和Clojure支持。实现IHashEq会更快。

对于
散列集
,equals是不够的(我试过了),
散列码
也是需要的。一件小事:
==
只为数值数据
用户>定义(==:a:a)=>ClassCastException clojure.lang.Keyword不能转换为java.lang.Number clojure.lang.Numbers.equal)(Numbers.java:206)
(deftype Ref [id]
  Object
  (equals [_ other] (= id (.id other))))
(deftype Ref [id]
  Object
  (equals [_ other] (= id (.id other)))
  (hashCode [_] id) 
  clojure.lang.IHashEq 
  (hasheq [_] id))