non-equality (=) of records nuance

Showing 1-6 of 6 messages
non-equality (=) of records nuance Greg D 3/18/14 1:40 PM
Greetings,

I'm confused by the failure of 2 record instances to compare as equal, only when generated by a protocol method and having extra fields.

The code below shows this, with uninformative REPL responses snipped. The attached file has similar code as a clojure.test.

Would somebody please help me understand the underlying mechanism. I'll need to develop a workaround to avoid confounding library users.

Thanks, Greg

user=> ;;; Set up protocol and records
user=> (defprotocol FooBar (clone [this]) (switch [this]))
user=> (defrecord Foo [])
user=> (defrecord Bar [])
user=> (extend-type Foo FooBar (clone [this] (map->Foo this)) (switch [this] (map->Bar this)))
user=> (extend-type Bar FooBar (clone [this] (map->Bar this)) (switch [this] (map->Foo this)))

user=> ;;; Create 4 (.equal) instances of Bar, no fields; all works as expected
user=> (def foo0 (->Foo))
user=> (def bar0 (->Bar))
user=> (def bar1 (->Bar))
user=> (def bar-switch-foo0 (switch foo0))
user=> (def bar-clone-bar0 (clone bar0))
user=> bar0
#user.Bar{}
user=> bar1
#user.Bar{}
user=> bar-switch-foo0
#user.Bar{}
user=> bar-clone-bar0
#user.Bar{}
user=> (= bar0 bar1)            ; gets expected true
true
user=> (= bar0 bar-switch-foo0) ; gets expected true
true
user=> (= bar0 bar-clone-bar0)  ; gets expected true
true

user=> ;;; Create 4 (.equal) instances of Bar with an added field; unexpected results
user=> (def x-foo0 (map->Foo {:field "xtra"}))
user=> (def x-bar0 (map->Bar {:field "xtra"}))
user=> (def x-bar1 (map->Bar {:field "xtra"}))
user=> (def bar-switch-x-foo0 (switch x-foo0))
user=> (def bar-clone-x-bar0 (clone x-bar0))
user=> x-bar0
#user.Bar{:field "xtra"}
user=> x-bar1
#user.Bar{:field "xtra"}
user=> bar-switch-x-foo0
#user.Bar{:field "xtra"}
user=> bar-clone-x-bar0
#user.Bar{:field "xtra"}
user=> (= x-bar0 x-bar1)                            ; gets expected true
true
user=> (= x-bar0 bar-switch-x-foo0)                 ; gets UNEXPECTED
false
user=> (= x-bar0 bar-clone-x-bar0)                  ; gets UNEXPECTED
false
user=> (= bar-switch-x-foo0 bar-clone-x-bar0)       ; gets UNEXPECTED
false
user=> (.equals x-bar0 bar-switch-x-foo0)           ; .equals is true
true
user=> (.equals x-bar0 bar-clone-x-bar0)            ; .equals is true
true
user=> (.equals bar-switch-x-foo0 bar-clone-x-bar0) ; .equals is true
true

non-equality (=) of records nuance Alex Miller 3/18/14 5:47 PM
What Clojure version are you on?
Re: non-equality (=) of records nuance Nicola Mometto 3/18/14 6:06 PM

Here's the bug:

user> (defrecord a [])
user.a
user> (defrecord b [])
user.b
user> (.__extmap (map->b (map->a {:a 1})))
#user.a{:a 1}
Re: non-equality (=) of records nuance Alex Miller 3/18/14 6:33 PM
Yeah that looks bad.
Re: non-equality (=) of records nuance Nicola Mometto 3/18/14 6:45 PM

I added a patch+tests here http://dev.clojure.org/jira/browse/CLJ-1388

Alex Miller writes:

> Yeah that looks bad.
Re: non-equality (=) of records nuance Greg D 3/18/14 7:27 PM
I'm on 1.5.1

I have a workaround:
  • instead of
    • (map->Foo this)
  • use
    •  (map->Foo (into {} this))

On Tuesday, March 18, 2014 5:47:46 PM UTC-7, Alex Miller wrote:
What Clojure version are you on?