Clojure Map and Record Uniformity

I found Clojure's behavior confusing regarding equality between maps and records. In this first example, we have two different types that are structurally equal. The equality function = returns true:

user> (defn make-one-map [] {:a "a" :b "b"}) #'user/make-one-map user> (def m1 (make-one-map)) #'user/m1 user> m1 {:a "a", :b "b"} user> (def m2 {:a "a" :b "b"}) #'user/m2 user> m2 {:a "a", :b "b"} user> (= m1 m2) true user> (type m1) clojure.lang.PersistentArrayMap user> (type m2) clojure.lang.PersistentHashMap 

In the second example, we have hashmap and a record that are structurally equivalent, but the = function returns false:

 user> (defrecord Titi [ab]) user.Titi user> (def titi (Titi. 1 2)) #'user/titi user> titi #user.Titi{:a 1, :b 2} user> (= titi {:a 1 :b 2}) false 

Why are there differences? I am using Clojure 1.3 and I found them very confusing.

+6
source share
2 answers

From docstring to defrecord :

In addition, defrecord will determine the type and value = and there will be specific Java.hashCode and .equals, consistent with the contract for java.util.Map.

Thus, when using = , the type is taken into account. Instead, you can use .equals :

 user> (.equals titi {:a 1 :b 2}) true 
+14
source

a PersistentArrayMap and a PersistentHashMap conceptually the same - as ArrayMap grows, it automatically converts to HashMap for performance reasons. User level code usually should not distinguish between the two.

A defrecord data type, on the other hand, does not match one of the other cards. This is a separate type that can implement completely different interfaces and should not be automatically replaced with any other type of card. This is not conceptually equal to a normal display, so = returns false.

+8
source

Source: https://habr.com/ru/post/908150/


All Articles