From 7d3c0ca7cbcfd88510455af5fe2ee96cfc80405d Mon Sep 17 00:00:00 2001 From: Nathan Marz Date: Mon, 29 Jun 2015 18:16:33 -0400 Subject: [PATCH 1/7] add test for first/last on empty structures --- VERSION | 2 +- test/clj/com/rpl/specter/core_test.clj | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index d1d899f..b49b253 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.5 +0.5.6 diff --git a/test/clj/com/rpl/specter/core_test.clj b/test/clj/com/rpl/specter/core_test.clj index 610b4f3..96fea73 100644 --- a/test/clj/com/rpl/specter/core_test.clj +++ b/test/clj/com/rpl/specter/core_test.clj @@ -362,3 +362,10 @@ (transform k1 inc) (transform k2 inc))) )) + +(deftest empty-pos-transform + (is (empty? (select FIRST []))) + (is (empty? (select LAST []))) + (is (= [] (transform FIRST inc []))) + (is (= [] (transform LAST inc []))) + ) From bcc15b1587548eeb3ce1884c20478471f9a7cde8 Mon Sep 17 00:00:00 2001 From: Nathan Marz Date: Mon, 29 Jun 2015 18:17:52 -0400 Subject: [PATCH 2/7] change FIRST/LAST to select nothing on empty sequences, closes #4 --- CHANGES.md | 4 ++++ src/clj/com/rpl/specter.clj | 4 ++-- src/clj/com/rpl/specter/impl.clj | 20 +++++++------------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0f54829..3aafe76 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,7 @@ +## 0.5.6 +* Add multi-path implementation +* change FIRST/LAST to select nothing on an empty sequence + ## 0.5.5 * Change filterer to accept a selector (that acts like selected? to determine whether or not to select value) diff --git a/src/clj/com/rpl/specter.clj b/src/clj/com/rpl/specter.clj index ee7f494..ea1ed40 100644 --- a/src/clj/com/rpl/specter.clj +++ b/src/clj/com/rpl/specter.clj @@ -113,9 +113,9 @@ (def VAL (->ValCollect)) -(def LAST (->LastStructurePath)) +(def LAST (->PosStructurePath last set-last)) -(def FIRST (->FirstStructurePath)) +(def FIRST (->PosStructurePath first set-first)) (defn srange-dynamic [start-fn end-fn] (->SRangePath start-fn end-fn)) diff --git a/src/clj/com/rpl/specter/impl.clj b/src/clj/com/rpl/specter/impl.clj index a171ed1..4ccd7bd 100644 --- a/src/clj/com/rpl/specter/impl.clj +++ b/src/clj/com/rpl/specter/impl.clj @@ -374,23 +374,17 @@ (collect-val [this structure] structure)) -(deftype LastStructurePath []) +(deftype PosStructurePath [getter setter]) (extend-protocol StructurePath - LastStructurePath + PosStructurePath (select* [this structure next-fn] - (next-fn (last structure))) + (if-not (empty? structure) + (next-fn ((.getter this) structure)))) (transform* [this structure next-fn] - (set-last structure (next-fn (last structure))))) - -(deftype FirstStructurePath []) - -(extend-protocol StructurePath - FirstStructurePath - (select* [this structure next-fn] - (next-fn (first structure))) - (transform* [this structure next-fn] - (set-first structure (next-fn (first structure))))) + (if (empty? structure) + structure + ((.setter this) structure (next-fn ((.getter this) structure)))))) (deftype WalkerStructurePath [afn]) From 8053245c48ad6cc1b3450b7cf2cf88549a07d520 Mon Sep 17 00:00:00 2001 From: Nathan Marz Date: Mon, 29 Jun 2015 18:30:30 -0400 Subject: [PATCH 3/7] allow sets to be used directly as selector (acts as filter) --- src/clj/com/rpl/specter.clj | 14 +++++++++----- src/clj/com/rpl/specter/impl.clj | 9 +++++++++ test/clj/com/rpl/specter/core_test.clj | 9 +++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/clj/com/rpl/specter.clj b/src/clj/com/rpl/specter.clj index ea1ed40..8bcb504 100644 --- a/src/clj/com/rpl/specter.clj +++ b/src/clj/com/rpl/specter.clj @@ -161,12 +161,16 @@ (extend-type clojure.lang.AFn StructurePath (select* [afn structure next-fn] - (if (afn structure) - (next-fn structure))) + (filter-select afn structure next-fn)) (transform* [afn structure next-fn] - (if (afn structure) - (next-fn structure) - structure))) + (filter-transform afn structure next-fn))) + +(extend-protocol StructurePath + clojure.lang.PersistentHashSet + (select* [aset structure next-fn] + (filter-select aset structure next-fn)) + (transform* [aset structure next-fn] + (filter-transform aset structure next-fn))) (defn collect [& selector] (->SelectCollector select (comp-paths* selector))) diff --git a/src/clj/com/rpl/specter/impl.clj b/src/clj/com/rpl/specter/impl.clj index 4ccd7bd..48e8994 100644 --- a/src/clj/com/rpl/specter/impl.clj +++ b/src/clj/com/rpl/specter/impl.clj @@ -532,3 +532,12 @@ (.paths this)) )) +(defn filter-select [afn structure next-fn] + (if (afn structure) + (next-fn structure))) + +(defn filter-transform [afn structure next-fn] + (if (afn structure) + (next-fn structure) + structure)) + diff --git a/test/clj/com/rpl/specter/core_test.clj b/test/clj/com/rpl/specter/core_test.clj index 96fea73..98d024d 100644 --- a/test/clj/com/rpl/specter/core_test.clj +++ b/test/clj/com/rpl/specter/core_test.clj @@ -369,3 +369,12 @@ (is (= [] (transform FIRST inc []))) (is (= [] (transform LAST inc []))) ) + +(defspec set-filter-test + (for-all+ + [k1 gen/keyword + k2 (gen/such-that #(not= k1 %) gen/keyword) + k3 (gen/such-that (complement #{k1 k2}) gen/keyword) + v (gen/vector (gen/elements [k1 k2 k3]))] + (= (filter #{k1 k2} v) (select [ALL #{k1 k2}] v)) + )) From ce837a39af63934953f3362d31821fbe5b2010a6 Mon Sep 17 00:00:00 2001 From: Nathan Marz Date: Mon, 29 Jun 2015 18:31:03 -0400 Subject: [PATCH 4/7] update changelog --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 3aafe76..7ab7d6d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,7 @@ ## 0.5.6 * Add multi-path implementation * change FIRST/LAST to select nothing on an empty sequence +* Allow sets to be used directly as selectors (acts as filter) ## 0.5.5 * Change filterer to accept a selector (that acts like selected? to determine whether or not to select value) From da554d824771398736a526a758815ea23f4f47e3 Mon Sep 17 00:00:00 2001 From: Nathan Marz Date: Mon, 29 Jun 2015 23:42:26 -0400 Subject: [PATCH 5/7] add test for select-one! returning nil result --- test/clj/com/rpl/specter/core_test.clj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/clj/com/rpl/specter/core_test.clj b/test/clj/com/rpl/specter/core_test.clj index 98d024d..e50920b 100644 --- a/test/clj/com/rpl/specter/core_test.clj +++ b/test/clj/com/rpl/specter/core_test.clj @@ -378,3 +378,8 @@ v (gen/vector (gen/elements [k1 k2 k3]))] (= (filter #{k1 k2} v) (select [ALL #{k1 k2}] v)) )) + +(deftest nil-select-one-test + (is (= nil (select-one! ALL [nil]))) + (is (thrown? Exception (select-one! ALL []))) + ) \ No newline at end of file From 1f2b4f03defb0669df1a7cfb05441322034b2aef Mon Sep 17 00:00:00 2001 From: Nathan Marz Date: Mon, 29 Jun 2015 23:43:15 -0400 Subject: [PATCH 6/7] fix bug in select-one! where nil result could not be returned --- src/clj/com/rpl/specter.clj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/clj/com/rpl/specter.clj b/src/clj/com/rpl/specter.clj index 8bcb504..8056e7f 100644 --- a/src/clj/com/rpl/specter.clj +++ b/src/clj/com/rpl/specter.clj @@ -37,9 +37,9 @@ (defn compiled-select-one! "Version of select-one! that takes in a selector pre-compiled with comp-paths" [selector structure] - (let [res (compiled-select-one selector structure)] - (when (nil? res) (throw-illegal "No elements found for params: " selector structure)) - res + (let [res (compiled-select selector structure)] + (when (not= 1 (count res)) (throw-illegal "Expected exactly one element for params: " selector structure)) + (first res) )) (defn select-one! From 5f2f1087a551a310ddfc10e11ea6bb44c79d7f50 Mon Sep 17 00:00:00 2001 From: Nathan Marz Date: Mon, 29 Jun 2015 23:44:18 -0400 Subject: [PATCH 7/7] 0.5.7 --- CHANGES.md | 3 +++ VERSION | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 7ab7d6d..8114222 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,6 @@ +## 0.5.7 +* Fix bug in select-one! which wouldn't allow nil result + ## 0.5.6 * Add multi-path implementation * change FIRST/LAST to select nothing on an empty sequence diff --git a/VERSION b/VERSION index b49b253..d3532a1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.6 +0.5.7