From 80b3857b086549626a671adbc8f7f3e24f3e81c5 Mon Sep 17 00:00:00 2001 From: nathanmarz Date: Sat, 11 Feb 2017 21:26:30 -0500 Subject: [PATCH] implement early termination using reduced, re-implement select-any/select-first in terms of it --- src/clj/com/rpl/specter.cljc | 13 +++++----- src/clj/com/rpl/specter/impl.cljc | 33 ++++++++++++------------- src/clj/com/rpl/specter/util_macros.clj | 2 +- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/clj/com/rpl/specter.cljc b/src/clj/com/rpl/specter.cljc index dd50090..948ccff 100644 --- a/src/clj/com/rpl/specter.cljc +++ b/src/clj/com/rpl/specter.cljc @@ -1066,13 +1066,14 @@ (late-bound-richnav [late1 (late-path path1) late2 (late-path path2)] (select* [this vals structure next-fn] - ;; on a select-any would be better to avoid doing late2 if late1 selects - ;; something - (let [res1 (i/exec-select* late1 vals structure next-fn) - res2 (i/exec-select* late2 vals structure next-fn)] - (if (identical? NONE res2) + (let [res1 (i/exec-select* late1 vals structure next-fn)] + (if (reduced? res1) res1 - res2))) + (let [res2 (i/exec-select* late2 vals structure next-fn)] + (if (identical? NONE res1) + res2 + res1 + ))))) (transform* [this vals structure next-fn] (let [s1 (i/exec-transform* late1 vals structure next-fn)] (i/exec-transform* late2 vals s1 next-fn))))) diff --git a/src/clj/com/rpl/specter/impl.cljc b/src/clj/com/rpl/specter/impl.cljc index 3ee7ca9..718d2da 100644 --- a/src/clj/com/rpl/specter/impl.cljc +++ b/src/clj/com/rpl/specter/impl.cljc @@ -306,10 +306,14 @@ (compiled-traverse* apath (fn [elem] - (let [curr (get-cell cell)] - (set-cell! cell (afn curr elem)))) + (let [curr (get-cell cell) + newv (afn curr elem)] + (set-cell! cell newv) + newv ; to support reduced handling during traverse + )) structure) - (get-cell cell))))) + (unreduced (get-cell cell)) + )))) (defn compiled-select* [path structure] @@ -350,24 +354,19 @@ ret))) -(defn compiled-select-first* [path structure] - (let [res (mutable-cell NONE) - result-fn (fn [structure] - (let [curr (get-cell res)] - (if (identical? curr NONE) - (set-cell! res structure))))] - (compiled-traverse* path result-fn structure) - (let [ret (get-cell res)] - (if (identical? ret NONE) - nil - ret)))) - (defn compiled-select-any* [path structure] - (compiled-traverse* path identity structure)) + (unreduced (compiled-traverse* path reduced structure))) + +(defn compiled-select-first* [path structure] + (let [ret (compiled-select-any* path structure)] + (if (identical? ret NONE) + nil + ret + ))) (defn compiled-selected-any?* [path structure] - (not= NONE (compiled-select-any* path structure))) + (not (identical? NONE (compiled-select-any* path structure)))) (defn terminal* [afn vals structure] (if (identical? vals []) diff --git a/src/clj/com/rpl/specter/util_macros.clj b/src/clj/com/rpl/specter/util_macros.clj index 9466958..2800ea9 100644 --- a/src/clj/com/rpl/specter/util_macros.clj +++ b/src/clj/com/rpl/specter/util_macros.clj @@ -6,7 +6,7 @@ (let [ret# (do ~@body)] (if (identical? ret# ~backup-res) curr# - ret#))) + (if (reduced? ret#) (reduced ret#) ret#)))) ~backup-res ~aseq))