From 1c21be226256868f7dafce7b7cdb5aa2ed4925ea Mon Sep 17 00:00:00 2001 From: Nathan Marz Date: Wed, 1 Jun 2016 12:02:41 -0400 Subject: [PATCH] minor performance optimizations to FIRST/LAST --- src/clj/com/rpl/specter.cljx | 4 +-- src/clj/com/rpl/specter/impl.cljx | 56 +++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/clj/com/rpl/specter.cljx b/src/clj/com/rpl/specter.cljx index efc476f..f7cdba3 100644 --- a/src/clj/com/rpl/specter.cljx +++ b/src/clj/com/rpl/specter.cljx @@ -155,9 +155,9 @@ (def VAL (i/->ValCollect)) -(def LAST (comp-paths (i/->PosNavigator last i/set-last))) +(def LAST (comp-paths (i/->PosNavigator i/get-last i/update-last))) -(def FIRST (comp-paths (i/->PosNavigator first i/set-first))) +(def FIRST (comp-paths (i/->PosNavigator i/get-first i/update-first))) (defnav ^{:doc "Uses start-fn and end-fn to determine the bounds of the subsequence diff --git a/src/clj/com/rpl/specter/impl.cljx b/src/clj/com/rpl/specter/impl.cljx index 4f569ab..1cc8cde 100644 --- a/src/clj/com/rpl/specter/impl.cljx +++ b/src/clj/com/rpl/specter/impl.cljx @@ -439,27 +439,47 @@ (defn- append [coll elem] (-> coll vec (conj elem))) -(defprotocol SetExtremes - (set-first [s val]) - (set-last [s val])) +(defprotocol UpdateExtremes + (update-first [s afn]) + (update-last [s afn])) -(defn- set-first-list [l v] - (cons v (rest l))) +(defprotocol GetExtremes + (get-first [s]) + (get-last [s])) -(defn- set-last-list [l v] - (append (butlast l) v)) +(defn- update-first-list [l afn] + (cons (afn (first l)) (rest l))) -(extend-protocol SetExtremes +(defn- update-last-list [l afn] + (append (butlast l) (afn (last l)))) + +(extend-protocol UpdateExtremes #+clj clojure.lang.PersistentVector #+cljs cljs.core/PersistentVector - (set-first [v val] - (assoc v 0 val)) - (set-last [v val] - (assoc v (-> v count dec) val)) + (update-first [v afn] + (let [val (get v 0)] + (assoc v 0 (afn val)) + )) + (update-last [v afn] + (conj (pop v) (afn (peek v))) + ) #+clj Object #+cljs default - (set-first [l val] - (set-first-list l val)) - (set-last [l val] - (set-last-list l val) + (update-first [l val] + (update-first-list l val)) + (update-last [l val] + (update-last-list l val) + )) + +(extend-protocol GetExtremes + #+clj clojure.lang.PersistentVector #+cljs cljs.core/PersistentVector + (get-first [v] + (get v 0)) + (get-last [v] + (peek v)) + #+clj Object #+cljs default + (get-first [s] + (first s)) + (get-last [s] + (last s) )) (defn walk-until [pred on-match-fn structure] @@ -592,7 +612,7 @@ (collect-val [this structure] structure)) -(deftype PosNavigator [getter setter]) +(deftype PosNavigator [getter updater]) (extend-protocol p/Navigator PosNavigator @@ -602,7 +622,7 @@ (transform* [this structure next-fn] (if (empty? structure) structure - ((.-setter this) structure (next-fn ((.-getter this) structure)))))) + ((.-updater this) structure next-fn)))) (defn srange-select [structure start end next-fn] (next-fn (-> structure vec (subvec start end))))