Back
diff (clj)
(source)function
(diff a b)
Recursively compares a and b, returning a tuple of
[things-only-in-a things-only-in-b things-in-both].
Comparison rules:
* For equal a and b, return [nil nil a].
* Maps are subdiffed where keys match and values differ.
* Sets are never subdiffed.
* All sequential things are treated as associative collections
by their indexes, with results returned as vectors.
* Everything else (including strings!) is treated as
an atom and compared for equality.
Examples
clojure
(ns clojure.test-clojure.numbers
(:use clojure.test
[clojure.test.generative :exclude (is)]
clojure.template)
(:require [clojure.data.generators :as gen]
[clojure.test-helper :as helper]))
;; == tests for numerical equality, returning true even for numbers
;; in different categories.
(all-pairs-equal #'== [(byte 0) (short 0) (int 0) (long 0)
(bigint 0) (biginteger 0)
(float -0.0) (double -0.0) -0.0M -0.00M
(float 0.0) (double 0.0) 0.0M 0.00M])
(all-pairs-equal #'== [(byte 2) (short 2) (int 2) (long 2)
(bigint 2) (biginteger 2)
(float 2.0) (double 2.0) 2.0M 2.00M])
(all-pairs-equal #'== [(/ 3 2) (float 1.5) (double 1.5) 1.50M 1.500M]))
(deftest test-min-max
(testing "min/max on different numbers of floats and doubles"
(are [xmin xmax a]
(and (= (Float. xmin) (min (Float. a)))
(= (Float. xmax) (max (Float. a)))
(= xmin (min a))
(= xmax (max a)))
0.0 0.0 0.0)
(are [xmin xmax a b]
(and (= (Float. xmin) (min (Float. a) (Float. b)))
(= (Float. xmax) (max (Float. a) (Float. b)))
(= xmin (min a b))
(= xmax (max a b)))
-1.0 0.0 0.0 -1.0
-1.0 0.0 -1.0 0.0
0.0 1.0 0.0 1.0
0.0 1.0 1.0 0.0)
(are [xmin xmax a b c]
(and (= (Float. xmin) (min (Float. a) (Float. b) (Float. c)))
(= (Float. xmax) (max (Float. a) (Float. b) (Float. c)))
(= xmin (min a b c))
(= xmax (max a b c)))
-1.0 1.0 0.0 1.0 -1.0
-1.0 1.0 0.0 -1.0 1.0
-1.0 1.0 -1.0 1.0 0.0))
(testing "min/max preserves type of winner"
(is (= java.lang.Long (class (max 10))))
(is (= java.lang.Long (class (max 1.0 10))))
(is (= java.lang.Long (class (max 10 1.0))))
(is (= java.lang.Long (class (max 10 1.0 2.0))))
(is (= java.lang.Long (class (max 1.0 10 2.0))))
(is (= java.lang.Long (class (max 1.0 2.0 10))))
(is (= java.lang.Double (class (max 1 2 10.0 3 4 5))))
(is (= java.lang.Long (class (min 10))))
(is (= java.lang.Long (class (min 1.0 -10))))
(is (= java.lang.Long (class (min -10 1.0))))
(is (= java.lang.Long (class (min -10 1.0 2.0))))
(is (= java.lang.Long (class (min 1.0 -10 2.0))))
(is (= java.lang.Long (class (min 1.0 2.0 -10))))
(is (= java.lang.Double (class (min 1 2 -10.0 3 4 5))))))
clojure
(ns clojure.test-clojure.java-interop
(:use clojure.test)
(:require [clojure.data :as data]
[clojure.inspector]
[clojure.pprint :as pp]
[clojure.set :as set]
[clojure.test-clojure.proxy.examples :as proxy-examples])
(:import java.util.Base64
(java.util.concurrent.atomic AtomicLong AtomicInteger)))
; different types
(are [type literal] (instance? literal type)
1 java.lang.Long
1.0 java.lang.Double
1M java.math.BigDecimal
\a java.lang.Character
"a" java.lang.String )
;https://clojure.atlassian.net/browse/CLJ-1973
(deftest test-proxy-method-order
(let [class-reader (clojure.asm.ClassReader. proxy-examples/proxy1-class-name)
method-order (atom [])
method-visitor (proxy [clojure.asm.ClassVisitor] [clojure.asm.Opcodes/ASM4 nil]
(visitMethod [access name descriptor signature exceptions]
(swap! method-order conj {:name name :descriptor descriptor})
nil))
_ (.accept class-reader method-visitor 0)
expected [{:name "<init>", :descriptor "()V"}
{:name "__initClojureFnMappings", :descriptor "(Lclojure/lang/IPersistentMap;)V"}
{:name "__updateClojureFnMappings", :descriptor "(Lclojure/lang/IPersistentMap;)V"}
{:name "__getClojureFnMappings", :descriptor "()Lclojure/lang/IPersistentMap;"}
{:name "clone", :descriptor "()Ljava/lang/Object;"}
{:name "hashCode", :descriptor "()I"}
{:name "toString", :descriptor "()Ljava/lang/String;"}
{:name "equals", :descriptor "(Ljava/lang/Object;)Z"}
{:name "a", :descriptor "(Ljava/io/File;)Z"}
{:name "a", :descriptor "(Ljava/lang/Boolean;)Ljava/lang/Object;"}
{:name "a", :descriptor "(Ljava/lang/Runnable;)Z"}
{:name "a", :descriptor "(Ljava/lang/String;)I"}
{:name "b", :descriptor "(Ljava/lang/String;)Ljava/lang/Object;"}
{:name "c", :descriptor "(Ljava/lang/String;)Ljava/lang/Object;"}
{:name "d", :descriptor "(Ljava/lang/String;)Ljava/lang/Object;"}
{:name "a", :descriptor "(Ljava/lang/Boolean;Ljava/lang/String;)I"}
{:name "a", :descriptor "(Ljava/lang/String;Ljava/io/File;)Z"}
{:name "a", :descriptor "(Ljava/lang/String;Ljava/lang/Runnable;)Z"}
{:name "a", :descriptor "(Ljava/lang/String;Ljava/lang/String;)I"}]
actual @method-order]
(is (= expected actual)
(with-out-str (pp/pprint (data/diff expected actual))))))
; different kinds of collections
(are [x] (and (= (alength (to-array x)) (count x))
(= (vec (to-array x)) (vec x)))
()
'(1 2)
[]
[1 2]
(sorted-set)
(sorted-set 1 2)
(int-array 0)
(int-array [1 2 3])
(is (= [nil 1 2] (seq (into-array [nil 1 2]))))
(let [types [Integer/TYPE
Byte/TYPE
Float/TYPE
Short/TYPE
Double/TYPE
Long/TYPE]
values [(byte 2) (short 3) (int 4) 5]]
(for [t types]
(let [a (into-array t values)]
(is (== (aget a 0) 2))
(is (== (aget a 1) 3))
(is (== (aget a 2) 4))
(is (== (aget a 3) 5)))))
; different kinds of collections
(are [x] (and (= (alength (into-array x)) (count x))
(= (vec (into-array x)) (vec x))
(= (alength (into-array Long/TYPE x)) (count x))
(= (vec (into-array Long/TYPE x)) (vec x)))
()
'(1 2)
[]
[1 2]
(sorted-set)
(sorted-set 1 2)
clojure
(ns clojure.test-clojure.data-structures
(:use clojure.test
[clojure.test.generative :exclude (is)])
(:require [clojure.test-clojure.generators :as cgen]
[clojure.data.generators :as gen]
[clojure.string :as string])
(:import [java.util Collection]))
(defn diff [s1 s2]
(seq (reduce disj (set s1) (set s2))))
; sorted-map, hash-map and array-map - classes differ, but content is equal
;; TODO: reimplement all-are with new do-template?
;; (all-are (not= (class _1) (class _2))
;; (sorted-map :a 1)
;; (hash-map :a 1)
;; (array-map :a 1))
;; (all-are (= _1 _2)
;; (sorted-map)
;; (hash-map)
;; (array-map))
;; (all-are (= _1 _2)
;; (sorted-map :a 1)
;; (hash-map :a 1)
;; (array-map :a 1))
;; (all-are (= _1 _2)
;; (sorted-map :a 1 :z 3 :c 2)
;; (hash-map :a 1 :z 3 :c 2)
;; (array-map :a 1 :z 3 :c 2))
; different types
(are [x] (= (count [x]) 1)
nil true false
0 0.0 "" \space
() [] #{} {} ))
; different data structures
(list true false nil)
'(true false nil)
(list 1 2.5 2/3 "ab" \x 'cd :kw)
'(1 2.5 2/3 "ab" \x cd :kw)
(list (list 1 2) [3 4] {:a 1 :b 2} #{:c :d})
'((1 2) [3 4] {:a 1 :b 2} #{:c :d})
(are [x y] (= x y)
; (class {:a 1}) => clojure.lang.PersistentArrayMap
(keys {}) nil
(keys {:a 1}) '(:a)
(keys {nil 1}) '(nil)
(diff (keys {:a 1 :b 2}) '(:a :b)) nil ; (keys {:a 1 :b 2}) '(:a :b)
; (class (sorted-map :a 1)) => clojure.lang.PersistentTreeMap
(keys (sorted-map)) nil
(keys (sorted-map :a 1)) '(:a)
(diff (keys (sorted-map :a 1 :b 2)) '(:a :b)) nil ; (keys (sorted-map :a 1 :b 2)) '(:a :b)
; (class (hash-map :a 1)) => clojure.lang.PersistentHashMap
(keys (hash-map)) nil
(keys (hash-map :a 1)) '(:a)
(diff (keys (hash-map :a 1 :b 2)) '(:a :b)) nil ) ; (keys (hash-map :a 1 :b 2)) '(:a :b)
(are [x y] (= x y)
; (class {:a 1}) => clojure.lang.PersistentArrayMap
(vals {}) nil
(vals {:a 1}) '(1)
(vals {nil 1}) '(1)
(diff (vals {:a 1 :b 2}) '(1 2)) nil ; (vals {:a 1 :b 2}) '(1 2)
; (class (sorted-map :a 1)) => clojure.lang.PersistentTreeMap
(vals (sorted-map)) nil
(vals (sorted-map :a 1)) '(1)
(diff (vals (sorted-map :a 1 :b 2)) '(1 2)) nil ; (vals (sorted-map :a 1 :b 2)) '(1 2)
; (class (hash-map :a 1)) => clojure.lang.PersistentHashMap
(vals (hash-map)) nil
(vals (hash-map :a 1)) '(1)
(diff (vals (hash-map :a 1 :b 2)) '(1 2)) nil ) ; (vals (hash-map :a 1 :b 2)) '(1 2)
; different data structures
(hash-set true false nil)
#{true false nil}
(hash-set 1 2.5 2/3 "ab" \x 'cd :kw)
#{1 2.5 2/3 "ab" \x 'cd :kw}
(hash-set (list 1 2) [3 4] {:a 1 :b 2} #{:c :d})
#{'(1 2) [3 4] {:a 1 :b 2} #{:c :d}}
; identity
(are [x] (= (disj x) x)
nil
#{}
#{1 2 3}
; different data types
#{nil
false true
0 42
0.0 3.14
2/3
0M 1M
\c
"" "abc"
'sym
:kw
[] [1 2]
{} {:a 1 :b 2}
#{} #{1 2}} )
(deftest map-equality-test
(let [empty-maps [ {}
(hash-map)
(array-map)
(sorted-map)
(sorted-map-by case-indendent-string-cmp) ]]
(doseq [m1 empty-maps, m2 empty-maps]
(is-same-collection m1 m2)))
(let [maps1 [ {"Banana" "like", "apple" "love", "7th" "indifferent"}
(hash-map "Banana" "like", "apple" "love", "7th" "indifferent")
(array-map "Banana" "like", "apple" "love", "7th" "indifferent")
(sorted-map "Banana" "like", "apple" "love", "7th" "indifferent")
(sorted-map-by case-indendent-string-cmp
"Banana" "like", "apple" "love", "7th" "indifferent") ]]
(doseq [m1 maps1, m2 maps1]
(is-same-collection m1 m2))))
babashka/babashka
(ns babashka.impl.data
{:no-doc true}
(:require
[babashka.impl.clojure.data :as data]
[sci.core :as sci :refer [copy-var]]))
(def data-namespace
{'diff (copy-var data/diff data-ns)
'equality-partition (copy-var data/equality-partition data-ns)})
jonase/eastwood
(ns testcases.unusednss4
(:use testcases.unusednss2)
(:require [clojure [string :as s]]
[clojure [repl :as r]]
[clojure.data :as d]))
(defmacro macro1
[options]
(if (map? options)
`(str (d/diff (:x options) (:y options)))
`(str (d/diff (first options) (second options)))))
ingesolvoll/kee-frame
(ns ^:no-doc kee-frame.event-logger
(:require [re-frame.interceptor :as i]
[clojure.data :as data]
[taoensso.timbre :as log]))
(log/debug (merge {:event event}
(when (seq effects)
{:side-effects effects})
(when (not= new-db ::not-found)
(let [[only-before only-after] (data/diff orig-db new-db)
db-changed? (or (some? only-before) (some? only-after))]
(when db-changed?
{:db-diff {:only-before only-before
:only-after only-after}})))))
context))))