defrecord and map equality?

133 views
Skip to first unread message

Ryan Twitchell

unread,
Jul 29, 2010, 11:51:57 PM7/29/10
to Clojure
Hi all,

I noticed (with a very recent git pull) the following asymmetric
behavior regarding = and records:

(defrecord my-record [a])

(def r (new my-record 1))
(def s (new my-record 1))

(= r s) ;; true
(= s r) ;; true
(= r {:a 1}) ;; false
(= {:a 1} r) ;; true

Is this intentional? (I hope not)

Also, what prompted this was my trying to do the following. In
general, what kind of behavior should we expect to see when mixing
records and other map types?

(replace {{:a 1} (new my-record 2)} [(new my-record 1)])

Currently this produces [#:user.my-record{:a 1}], where I was hoping
to get [#:user.my-record{:a 2}]

Frederick Polgardy

unread,
Jul 30, 2010, 11:37:59 AM7/30/10
to clo...@googlegroups.com
I'm sure it's not intentional, but it makes sense. In the first case, the comparison delegates to `r`'s equals() method, which would return false because {:a 1} isn't a `my-record`. In the second case, the comparison delegates to `{:a 1}`'s equals() method, which is a PersistentArrayMap, which would return true, because it's just looking for equality of map entries. Not sure how to make this behave consistently without introducing a lot of weirdness into the language.

-Fred

--
Science answers questions; philosophy questions answers.

Nicolas Oury

unread,
Jul 30, 2010, 12:25:14 PM7/30/10
to clo...@googlegroups.com
On Fri, Jul 30, 2010 at 4:51 AM, Ryan Twitchell <metat...@gmail.com> wrote:
>
> (= r s)        ;; true
> (= s r)        ;; true
> (= r {:a 1})   ;; false
> (= {:a 1} r)   ;; true
>
> Is this intentional? (I hope not)
>

The three first are documented in (doc defrecord)
"In addition, defrecord will define type-and-value-based equality and
hashCode."

I don't know if the last one is intentional or not.

Best,

Nicolas.

Rich Hickey

unread,
Aug 4, 2010, 3:02:51 PM8/4/10
to Clojure
This, and several other symmetry problems, are now fixed:

http://github.com/clojure/clojure/commit/ac484ba40cc1d94d42ce59e9df92b13e98ed0b6e

The policy is: = includes the type and .equals doesn't. In this way
records can still be proper j.u.Maps and = remains most useful for
records (e.g. including type).

Thanks for the report,

Rich
Reply all
Reply to author
Forward
0 new messages