From 68ea61b2793336ba305ad2b6aa117e61de81be98 Mon Sep 17 00:00:00 2001 From: Caleb Figgers Date: Fri, 1 Sep 2023 02:28:12 -0500 Subject: [PATCH 1/2] Algorithm refinement, bugfixes, expanded tests --- spork/data.janet | 54 +++++++++++++++++--------------------------- test/suite0021.janet | 32 +++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 34 deletions(-) diff --git a/spork/data.janet b/spork/data.janet index 5bd8d00..60180db 100644 --- a/spork/data.janet +++ b/spork/data.janet @@ -34,24 +34,22 @@ (let [va (safe-in a k) vb (safe-in b k) [a* b* ab] (diff va vb) - in-a (in? k (keys a)) - in-b (in? k (keys b)) - same (and in-a in-b + same (and (in? k (keys a)) (in? k (keys b)) (or (not (nil? ab)) (and (nil? va) (nil? vb))))] - [(when (and in-a (or (not (nil? a*)) (not same))) {k a*}) - (when (and in-b (or (not (nil? b*)) (not same))) {k b*}) + [(when (and (in? k (keys a)) (or (not (nil? a*)) (not same))) {k a*}) + (when (and (in? k (keys b)) (or (not (nil? b*)) (not same))) {k b*}) (when same {k ab})])) -(defn- diff-associative [a b ks] - (reduce - (fn [diff1 diff2] - (map |(if (empty? $) nil $) - (map |(merge (or $0 {}) (or $1 {})) diff1 diff2))) - [nil nil nil] - (map - (partial diff-associative-key a b) - ks))) +(defn- diff-associative [a b &opt ks] + (default ks (distinct (array/concat (keys a) (keys b)))) + (let [reduced (reduce + (fn [diff1 diff2] + (map |(if (empty? $) nil $) + (map |(merge (or $0 @{}) (or $1 @{})) diff1 diff2))) + [nil nil nil] + (map (partial diff-associative-key a b) ks))] + reduced)) (defn- diff-sequential [a b] (map vectorize (diff-associative @@ -59,27 +57,17 @@ (if (array? b) b (array ;b)) (range (max (length a) (length b)))))) -(defn- diff-similar [kind a b] - (cond - (in? kind [:array :tuple]) (diff-sequential a b) - (in? kind [:table :struct]) (diff-associative a b (distinct (array/concat (keys a) (keys b)))) - (atom-diff a b))) - -(defn- categorize [x] - (cond - (in? (type x) [:array :tuple]) :sequence - (in? (type x) [:table :struct]) :associative - :atom)) - (varfn diff ``` Compares a and b recursively. Returns an array of - [things-only-in-a things-only-in-b things-in-both]. + @[things-only-in-a things-only-in-b things-in-both]. ``` [a b] - (if (= a b) - @[nil nil (cond (tuple? a) (array ;a) - (struct? a) (struct/to-table a) a)] - (if (= (categorize a) (categorize b)) - (diff-similar (type a) a b) - (atom-diff a b)))) + (if (deep= a b) + @[nil nil (postwalk |(cond (tuple? $) (array ;$) + (struct? $) (struct/to-table $) $) a)] + (do + (cond + (all indexed? [a b]) (diff-sequential a b) + (all dictionary? [a b]) (diff-associative a b) + (atom-diff a b))))) diff --git a/test/suite0021.janet b/test/suite0021.janet index a95fca4..fd79d76 100644 --- a/test/suite0021.janet +++ b/test/suite0021.janet @@ -51,7 +51,37 @@ [{:a 1 :b 2} @{:a 1 :b 2 :c 4 :d 5} @[nil @{:c 4 :d 5} @{:a 1 :b 2}] "Should be: Struct and Table, different"] [@[1 2 3] [1 2 3] @[nil nil @[1 2 3]] "Should be: Array and Tuple, same"] - [@[1 2 3] [1 2 3 4 5] @[nil @[nil nil nil 4 5] @[1 2 3]] "Should be: Array and Tuple, different"]]) + [@[1 2 3] [1 2 3 4 5] @[nil @[nil nil nil 4 5] @[1 2 3]] "Should be: Array and Tuple, different"] + + [@{:a [1 2 {:b {:c 3}}] 5 @[:d :e 4] 6 @{7 {:f "test" :g {8 [9 10 11] :h 12}}}} + @{:a [1 2 {:b {:c 3}}] 5 @[:d :e 4] 6 @{7 {:f "test" :g {8 [9 10 11] :h 12}}}} + @[nil nil @{6 @{7 @{:f "test" :g @{8 @[9 10 11] :h 12}}} :a @[1 2 @{:b @{:c 3}}] 5 @[:d :e 4]}] + "Should be: Nested Complex Data Structures, same"] + + [@{:a [1 2 {:b {:c 3}}] 5 @[:d :e 4] 6 @{7 {:f "test" :g {8 [9 10 11] :h 12}}}} + @{:a [1 2 {:b {:c 3}}] 5 @[:d :e 4] 6 @{7 {:f "test" :g {8 [9 10 {:z 100} 11] :h 12}}}} + @[@{6 @{7 @{:g @{8 @[nil nil 11]}}}} @{6 @{7 @{:g @{8 @[nil nil {:z 100} 11]}}}} @{5 @[:d :e 4] 6 @{7 @{:f "test" :g @{8 @[9 10] :h 12}}} :a @[1 2 @{:b @{:c 3}}]}] + "Should be: Nested Complex Data Structures, deep insertion"] + + [@{:a [1 2 {:b {:c 3}}] 5 @[:d :e 4] 6 @{7 {:f "test" :g {8 [9 10 11] :h 12}}}} + @{:a [1 2 {:b {:c 3}}] 5 @[:d :e 4] 6 @{7 {:f "test" :g {8 [9 10 11]}}}} + @[@{6 @{7 @{:g @{:h 12}}}} nil @{6 @{7 @{:g @{8 @[9 10 11]} :f "test"}} 5 @[:d :e 4] :a @[1 2 @{:b @{:c 3}}]}] + "Should be: Nested Complex Data Structures, deep delete"] + + [@{:a [1 2 {:b {:c 3}}] 5 @[:d :e 4] 6 @{7 {:f "test" :g {8 [9 10 11] :h 12}}}} + @{:a [1 2 {:b {:c 3}}] 5 @[:d :e 4] 6 @{7 {:f "test" :g {8 [:z 10 11] :h 12}}}} + @[@{6 @{7 @{:g @{8 @[9]}}}} @{6 @{7 @{:g @{8 @[:z]}}}} @{6 @{7 @{:f "test" :g @{8 @[nil 10 11] :h 12}}} 5 @[:d :e 4] :a @[1 2 @{:b @{:c 3}}]}] + "Should be: Nested Complex Data Structures, deep update"] + + [@{:a [1 2 {:b {:c 3}}] 5 @[:d :e 4] 6 @{7 {:f "test" :g {8 [9 10 11] :h 12}}}} + @{:a [1 2 {:b {:c 3}}] 5 @[:d :e 4] 6 @{7 {:f "test" :g {8 {:z 100 :x 10000 :y 100000} :h 12}}}} + @[@{6 @{7 @{:g @{8 [9 10 11]}}}} @{6 @{7 @{:g @{8 {:x 10000 :y 100000 :z 100}}}}} @{:a @[1 2 @{:b @{:c 3}}] 5 @[:d :e 4] 6 @{7 @{:f "test" :g @{:h 12}}}}] + "Should be: Nested Complex Data Structures, deep update of a whole structure"] + + [@{:a [1 2 {:b {:c 3}}] 5 @[:d :e 4] 6 @{7 {:f "test" :g {8 [9 10 11] :h 12}}}} + @{:zz [1 10000 {:b {:c 3}}] 5 @[:d :e 1000] 6 @{7 {:f "test" :g {8 [9 10 11 {:z 10}] :h 12}}}} + @[@{5 @[nil nil 4] :a [1 2 {:b {:c 3}}]} @{5 @[nil nil 1000] 6 @{7 @{:g @{8 @[nil nil nil {:z 10}]}}} :zz [1 10000 {:b {:c 3}}]} @{5 @[:d :e] 6 @{7 @{:f "test" :g @{8 @[9 10 11] :h 12}}}}] + "Should be: Nested Complex Data Structures, multiple deep updates"]]) (map |(diff-assert ;$) cases) From 0c0a8978418f5aff63d948bd397608bdb28cd63a Mon Sep 17 00:00:00 2001 From: Caleb Figgers Date: Fri, 1 Sep 2023 02:46:04 -0500 Subject: [PATCH 2/2] Corrected `(start-suite)` in suite0021 --- test/suite0021.janet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite0021.janet b/test/suite0021.janet index fd79d76..d2ec916 100644 --- a/test/suite0021.janet +++ b/test/suite0021.janet @@ -1,7 +1,7 @@ (use ../spork/test) (import ../spork/data :as d) -(start-suite) +(start-suite 21) (assert-docs "/spork/data")