Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure value equality and sets

Tags:

set

clojure

If I have a custom type and I use it to create two separate instances having precisely the same values, what method could I use to determine that the two things are equivalent? identical? and = and == don't seem to work. I would have expected there to be some protocol for setting up type comparisons. Ultimately, I would like it so that it would be impossible to add equivalent things to a set.

(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

= works with defrecord, but how would I define = for deftype?

like image 909
Mario Avatar asked Dec 14 '22 19:12

Mario


1 Answers

In your deftype, extend Object and implement equals to give them equality semantics:

(deftype Ref [id]
  Object
  (equals [_ other] (= id (.id other))))

Set containment will also require hashcode support:

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

I implemented both Java hash support and Clojure hasheq support there. Implementing IHashEq will be faster.

like image 151
Alex Miller Avatar answered Jan 25 '23 19:01

Alex Miller