[Git][clojure-team/fast-zip-clojure][upstream] New upstream version 0.7.0+really0.5.0

Jérôme Charaoui (@lavamind) gitlab at salsa.debian.org
Sat Jul 9 01:25:37 BST 2022



Jérôme Charaoui pushed to branch upstream at Debian Clojure Maintainers / fast-zip-clojure


Commits:
4399f948 by Jérôme Charaoui at 2022-07-08T17:02:48-04:00
New upstream version 0.7.0+really0.5.0
- - - - -


10 changed files:

- BENCHMARKS.md
- CHANGES.md
- README.md
- benchmarks/fast_zip/core_bench.clj
- benchmarks/fast_zip/core_bench.cljs
- project.clj
- + src/clj/fast_zip/core.clj
- src/fast_zip/core.cljc → src/cljs/fast_zip/core.cljs
- test/fast_zip/core_test.cljc → test/clj/fast_zip/core_test.clj
- + test/cljs/fast_zip/core_test.cljs


Changes:

=====================================
BENCHMARKS.md
=====================================
@@ -1,247 +1,5 @@
 # Benchmark History
 
-## 0.7.0
-
-Run on a Late 2012 Mac mini witha 2.6 GHZ core i7, osx 10.10.5 and java 1.8.0_45-b14.
-
-### ClojureScript
-
-    Benchmark: vector zip walk...
-    :clojure.zip.walk x 209 ops/sec ±0.68% (91 runs sampled)
-    :fast-zip.walk x 695 ops/sec ±1.03% (94 runs sampled)
-    Fastest is :fast-zip.walk
-    Benchmark: vector zip edit...
-    :clojure.zip.edit x 116 ops/sec ±1.08% (77 runs sampled)
-    :fast-zip.edit x 266 ops/sec ±0.69% (93 runs sampled)
-    Fastest is :fast-zip.edit
-    
-### Clojure
-
-    WARNING: Final GC required 1.1305691949835102 % of runtime
-    Goal:  Benchmark vector zip walk.
-    -----
-    Case:  :clojure.zip
-    Evaluation count : 51360 in 60 samples of 856 calls.
-                 Execution time mean : 1.206185 ms
-        Execution time std-deviation : 29.527194 µs
-       Execution time lower quantile : 1.179620 ms ( 2.5%)
-       Execution time upper quantile : 1.239860 ms (97.5%)
-                       Overhead used : 1.809668 ns
-
-    Found 3 outliers in 60 samples (5.0000 %)
-    	low-severe	 2 (3.3333 %)
-    	low-mild	 1 (1.6667 %)
-     Variance from outliers : 12.5608 % Variance is moderately inflated by outliers
-
-    Case:  :fast-zip
-    Evaluation count : 554760 in 60 samples of 9246 calls.
-                 Execution time mean : 108.874189 µs
-        Execution time std-deviation : 1.450027 µs
-       Execution time lower quantile : 106.084605 µs ( 2.5%)
-       Execution time upper quantile : 112.005702 µs (97.5%)
-                       Overhead used : 1.809668 ns
-
-    Goal:  Benchmark vector zip edit.
-    -----
-    Case:  :clojure.zip
-    Evaluation count : 12660 in 60 samples of 211 calls.
-                 Execution time mean : 5.047109 ms
-        Execution time std-deviation : 99.896647 µs
-       Execution time lower quantile : 4.918917 ms ( 2.5%)
-       Execution time upper quantile : 5.292446 ms (97.5%)
-                       Overhead used : 1.809668 ns
-
-    Found 2 outliers in 60 samples (3.3333 %)
-    	low-severe	 2 (3.3333 %)
-     Variance from outliers : 7.8717 % Variance is slightly inflated by outliers
-
-    Case:  :fast-zip
-    Evaluation count : 112260 in 60 samples of 1871 calls.
-                 Execution time mean : 536.307234 µs
-        Execution time std-deviation : 6.423185 µs
-       Execution time lower quantile : 521.727835 µs ( 2.5%)
-       Execution time upper quantile : 545.561598 µs (97.5%)
-                       Overhead used : 1.809668 ns
-
-## 0.6.1
-
-Run on a MBP2010 with a 2.66ghz core i7, osx 10.8.5 and java 1.8.0_25-b17.
-
-### ClojureScript
-
-    Benchmark: vector zip walk...
-    :clojure.zip.walk x 93.01 ops/sec ±5.02% (73 runs sampled)
-    :fast-zip.walk x 586 ops/sec ±1.26% (89 runs sampled)
-    Fastest is :fast-zip.walk
-    Benchmark: vector zip edit...
-    :clojure.zip.edit x 41.74 ops/sec ±1.45% (57 runs sampled)
-    :fast-zip.edit x 114 ops/sec ±1.41% (74 runs sampled)
-    Fastest is :fast-zip.edit
-
-### Clojure
-
-    WARNING: Final GC required 3.090076669784014 % of runtime
-    Goal:  Benchmark vector zip edit.
-    -----
-    Case:  :fast-zip
-    Evaluation count : 107640 in 60 samples of 1794 calls.
-                 Execution time mean : 576.321696 µs
-        Execution time std-deviation : 57.513398 µs
-       Execution time lower quantile : 526.397688 µs ( 2.5%)
-       Execution time upper quantile : 713.719117 µs (97.5%)
-                       Overhead used : 2.121629 ns
-    
-    Found 2 outliers in 60 samples (3.3333 %)
-    	low-severe	 1 (1.6667 %)
-    	low-mild	 1 (1.6667 %)
-     Variance from outliers : 70.3236 % Variance is severely inflated by outliers
-    
-    Case:  :clojure.zip
-    Evaluation count : 34500 in 60 samples of 575 calls.
-                 Execution time mean : 1.819284 ms
-        Execution time std-deviation : 163.955858 µs
-       Execution time lower quantile : 1.696950 ms ( 2.5%)
-       Execution time upper quantile : 2.178507 ms (97.5%)
-                       Overhead used : 2.121629 ns
-    
-    Found 6 outliers in 60 samples (10.0000 %)
-    	low-severe	 4 (6.6667 %)
-    	low-mild	 2 (3.3333 %)
-     Variance from outliers : 65.2416 % Variance is severely inflated by outliers
-    
-    Goal:  Benchmark vector zip walk.
-    -----
-    Case:  :fast-zip
-    Evaluation count : 592080 in 60 samples of 9868 calls.
-                 Execution time mean : 102.383653 µs
-        Execution time std-deviation : 1.349685 µs
-       Execution time lower quantile : 100.804221 µs ( 2.5%)
-       Execution time upper quantile : 106.239075 µs (97.5%)
-                       Overhead used : 2.121629 ns
-    
-    Found 4 outliers in 60 samples (6.6667 %)
-    	low-severe	 3 (5.0000 %)
-    	low-mild	 1 (1.6667 %)
-     Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
-    
-    Case:  :clojure.zip
-    Evaluation count : 54240 in 60 samples of 904 calls.
-                 Execution time mean : 1.152677 ms
-        Execution time std-deviation : 98.687775 µs
-       Execution time lower quantile : 1.078808 ms ( 2.5%)
-       Execution time upper quantile : 1.423912 ms (97.5%)
-                       Overhead used : 2.121629 ns
-    
-    Found 8 outliers in 60 samples (13.3333 %)
-    	low-severe	 5 (8.3333 %)
-    	low-mild	 3 (5.0000 %)
-     Variance from outliers : 61.9083 % Variance is severely inflated by outliers
-
-## 0.6.0
-
-Added new benchmarks for node editing. Existing/previous benchmark goal now named as "vector zip walk"...
-
-Run on a MBP2010 with a 2.66ghz core i7, osx 10.8.5 and java 1.8.0_25-b17.
-
-### ClojureScript
-
-    Benchmark: vector zip walk...
-    :clojure.zip.walk x 69.52 ops/sec ±3.58% (67 runs sampled)
-    :fast-zip.walk x 394 ops/sec ±1.88% (89 runs sampled)
-    Fastest is :fast-zip
-    Benchmark: vector zip edit...
-    :clojure.zip.edit x 33.89 ops/sec ±2.66% (61 runs sampled)
-    :fast-zip.edit x 89.38 ops/sec ±2.13% (78 runs sampled)
-    Fastest is :fast-zip.edit
-
-### Clojure
-
-    WARNING: Final GC required 2.904199000536039 % of runtime
-    Goal:  Benchmark vector zip edit.
-    -----
-    Case:  :fast-zip
-    Evaluation count : 96600 in 60 samples of 1610 calls.
-                 Execution time mean : 613.696756 µs
-        Execution time std-deviation : 23.370402 µs
-       Execution time lower quantile : 588.826153 µs ( 2.5%)
-       Execution time upper quantile : 687.558243 µs (97.5%)
-                       Overhead used : 2.997006 ns
-
-    Found 3 outliers in 60 samples (5.0000 %)
-    	low-severe	 3 (5.0000 %)
-     Variance from outliers : 23.8777 % Variance is moderately inflated by outliers
-
-    Case:  :clojure.zip
-    Evaluation count : 27420 in 60 samples of 457 calls.
-                 Execution time mean : 2.143100 ms
-        Execution time std-deviation : 55.341182 µs
-       Execution time lower quantile : 2.046640 ms ( 2.5%)
-       Execution time upper quantile : 2.248948 ms (97.5%)
-                       Overhead used : 2.997006 ns
-
-    Goal:  Benchmark vector zip walk.
-    -----
-    Case:  :fast-zip
-    Evaluation count : 578700 in 60 samples of 9645 calls.
-                 Execution time mean : 106.602340 µs
-        Execution time std-deviation : 3.705304 µs
-       Execution time lower quantile : 101.726377 µs ( 2.5%)
-       Execution time upper quantile : 117.508157 µs (97.5%)
-                       Overhead used : 2.997006 ns
-
-    Found 5 outliers in 60 samples (8.3333 %)
-    	low-severe	 2 (3.3333 %)
-    	low-mild	 3 (5.0000 %)
-     Variance from outliers : 20.6548 % Variance is moderately inflated by outliers
-
-    Case:  :clojure.zip
-    Evaluation count : 46020 in 60 samples of 767 calls.
-                 Execution time mean : 1.326133 ms
-        Execution time std-deviation : 32.156029 µs
-       Execution time lower quantile : 1.262908 ms ( 2.5%)
-       Execution time upper quantile : 1.387965 ms (97.5%)
-                       Overhead used : 2.997006 ns
-
-    Found 1 outliers in 60 samples (1.6667 %)
-    	low-severe	 1 (1.6667 %)
-     Variance from outliers : 12.5459 % Variance is moderately inflated by outliers
-
-## 0.5.1
-
-Run on a mac mini with a 2.6ghz core i7, osx 10.9.5, node.js 0.10.31,
-and java 1.7.0_51. ClojureScript uses simple optimization.
-
-### ClojureScript
-
-    :clojure.zip x 114 ops/sec ±0.64% (85 runs sampled)
-    :fast-zip x 197 ops/sec ±0.62% (88 runs sampled)
-    Fastest is :fast-zip
-
-### Clojure
-
-    ======================
-    WARNING: Final GC required 1.352547229118579 % of runtime
-    Goal:  Benchmark vector zip.
-    -----
-    Case:  :clojure.zip
-    Evaluation count : 58260 in 60 samples of 971 calls.
-                 Execution time mean : 1.049589 ms
-        Execution time std-deviation : 17.962641 µs
-       Execution time lower quantile : 1.018927 ms ( 2.5%)
-       Execution time upper quantile : 1.082843 ms (97.5%)
-                       Overhead used : 1.896478 ns
-
-    Case:  :fast-zip
-    Evaluation count : 326400 in 60 samples of 5440 calls.
-                 Execution time mean : 185.443364 µs
-        Execution time std-deviation : 2.938738 µs
-       Execution time lower quantile : 181.131376 µs ( 2.5%)
-       Execution time upper quantile : 192.279133 µs (97.5%)
-                       Overhead used : 1.896478 ns
-
-    Found 2 outliers in 60 samples (3.3333 %)
-        low-severe	 2 (3.3333 %)
-     Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
 
 ## 0.5.0
 
@@ -249,13 +7,11 @@ Run on a mac mini with a 2.6ghz core i7, osx 10.9.5, node.js 0.10.31,
 and java 1.7.0_51. ClojureScript uses simple optimization.
 
 ### ClojureScript
-
     :clojure.zip x 116 ops/sec ±0.65% (83 runs sampled)
     :fast-zip x 194 ops/sec ±0.85% (92 runs sampled)
     Fastest is :fast-zip 
 
 ### Clojure
-
     ======================
     WARNING: Final GC required 1.467359386689346 % of runtime
     Goal:  Benchmark vector zip.
@@ -337,4 +93,4 @@ Run on a mac mini with a 2.6ghz core i7 and osx version 10.9.1.
 
     Found 1 outliers in 60 samples (1.6667 %)
         low-severe	 1 (1.6667 %)
-     Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
+     Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
\ No newline at end of file


=====================================
CHANGES.md
=====================================
@@ -1,29 +1,5 @@
 # Release History
 
-## 0.7.0
-
-* Replace CLJX sources with CLJC (reader conditionals)
-* Update CLJ & CLJS dependencies (1.7.x)
-* Remove Piggieback & Austin dev dependencies
-
-## 0.6.1
-
-* Add ZipperOps deftype to minimize copying effort for new ZipperLocation instances
-
-## 0.6.0
-
-* Switch CLJ version to `deftype` implementation for further 2x speedup
-* Refactor project as CLJX setup (to avoid/minimize code duplication)
-* Update benchmark setup for both CLJ & CLJS, add benchmarks
-
-## 0.5.2
-
-* Bug fix for leftmost.
-
-## 0.5.1
-
-* Avoid redundant calls to up internally.
-
 ## 0.5.0
 
 * ClojureScript support thanks to Joel Holdbrooks.
@@ -36,4 +12,4 @@
 
 ## 0.3.0
 
-* Initial version.
+* Initial version.
\ No newline at end of file


=====================================
README.md
=====================================
@@ -1,119 +1,60 @@
 # fast-zip
 
-A modified version of [clojure.zip](http://clojuredocs.org/clojure.zip) that
-uses `deftype` internally and is written in CLJX format.
+A modified version of clojure.zip that uses records internally.
 
 ## Usage
 
-For Clojure 1.7 use:
-
 ```clojure
-[fast-zip "0.7.0"]
+[fast-zip "0.5.0"]
 ```
 
-For previous versions use:
-
-```clojure
-[fast-zip "0.6.1"]
-```
-
-This is a drop in replacement for clojure.zip. Simply require `fast-zip.core`
-instead of `clojure.zip`.
+This is a drop in replacement for clojure.zip. Simply require ``fast-zip.core``
+instead of ``clojure.zip``.
 
 ## Benchmark
 
-Since 0.6.1 a benchmark run consists of two analysis goals:
-
-1. "walk" traverses a vector zip of three levels of ints and sums the numbers (reduction over leaves)
-2. "edit" same setup as for "walk", but actually edits each leaf `(* n 10)` and applies all changes at the end
-
-The current snapshot version of this lib is roughly twice as fast as the 0.5.2 release...
+The below  traverses a vector zip with three levels and sums the numbers. To
+run, use ``lein perforate``.
 
-[Historical benchmarks for each version](BENCHMARKS.md)
-
-### Clojure
-
-To run, use `lein perforate`.
-
-    WARNING: Final GC required 2.904199000536039 % of runtime
-    Goal:  Benchmark vector zip edit.
+    ======================
+    WARNING: Final GC required 1.450308932831415 % of runtime
+    Goal:  Benchmark vector zip.
     -----
     Case:  :fast-zip
-    Evaluation count : 96600 in 60 samples of 1610 calls.
-                 Execution time mean : 613.696756 µs
-        Execution time std-deviation : 23.370402 µs
-       Execution time lower quantile : 588.826153 µs ( 2.5%)
-       Execution time upper quantile : 687.558243 µs (97.5%)
-                       Overhead used : 2.997006 ns
+    Evaluation count : 246120 in 60 samples of 4102 calls.
+                 Execution time mean : 242.777689 µs
+        Execution time std-deviation : 1.965914 µs
+       Execution time lower quantile : 238.996103 µs ( 2.5%)
+       Execution time upper quantile : 247.075613 µs (97.5%)
+                       Overhead used : 1.947263 ns
 
-    Found 3 outliers in 60 samples (5.0000 %)
-    	low-severe	 3 (5.0000 %)
-     Variance from outliers : 23.8777 % Variance is moderately inflated by outliers
+    Found 2 outliers in 60 samples (3.3333 %)
+        low-severe	 2 (3.3333 %)
+     Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
 
     Case:  :clojure.zip
-    Evaluation count : 27420 in 60 samples of 457 calls.
-                 Execution time mean : 2.143100 ms
-        Execution time std-deviation : 55.341182 µs
-       Execution time lower quantile : 2.046640 ms ( 2.5%)
-       Execution time upper quantile : 2.248948 ms (97.5%)
-                       Overhead used : 2.997006 ns
-
-    Goal:  Benchmark vector zip walk.
-    -----
-    Case:  :fast-zip
-    Evaluation count : 578700 in 60 samples of 9645 calls.
-                 Execution time mean : 106.602340 µs
-        Execution time std-deviation : 3.705304 µs
-       Execution time lower quantile : 101.726377 µs ( 2.5%)
-       Execution time upper quantile : 117.508157 µs (97.5%)
-                       Overhead used : 2.997006 ns
-
-    Found 5 outliers in 60 samples (8.3333 %)
-    	low-severe	 2 (3.3333 %)
-    	low-mild	 3 (5.0000 %)
-     Variance from outliers : 20.6548 % Variance is moderately inflated by outliers
+    Evaluation count : 62820 in 60 samples of 1047 calls.
+                 Execution time mean : 960.326181 µs
+        Execution time std-deviation : 4.915537 µs
+       Execution time lower quantile : 950.592132 µs ( 2.5%)
+       Execution time upper quantile : 969.813479 µs (97.5%)
+                       Overhead used : 1.947263 ns
 
-    Case:  :clojure.zip
-    Evaluation count : 46020 in 60 samples of 767 calls.
-                 Execution time mean : 1.326133 ms
-        Execution time std-deviation : 32.156029 µs
-       Execution time lower quantile : 1.262908 ms ( 2.5%)
-       Execution time upper quantile : 1.387965 ms (97.5%)
-                       Overhead used : 2.997006 ns
-
-    Found 1 outliers in 60 samples (1.6667 %)
-    	low-severe	 1 (1.6667 %)
-     Variance from outliers : 12.5459 % Variance is moderately inflated by outliers
-
-### ClojureScript
-
-For the clojurescript version, make sure you have node.js installed
-along with the [benchmark](https://www.npmjs.com/package/benchmark)
-NPM module. Then use `lein clean-bench`
-
-    Benchmark: vector zip walk...
-    :clojure.zip.walk x 69.52 ops/sec ±3.58% (67 runs sampled)
-    :fast-zip.walk x 394 ops/sec ±1.88% (89 runs sampled)
-    Fastest is :fast-zip
-    Benchmark: vector zip edit...
-    :clojure.zip.edit x 33.89 ops/sec ±2.66% (61 runs sampled)
-    :fast-zip.edit x 89.38 ops/sec ±2.13% (78 runs sampled)
-    Fastest is :fast-zip.edit
+For the clojurescript version, make sure you have node.js installed along
+with the ``benchmark`` module. Then use ``lein clean-bench``
 
 ## TODO
 
 * Create benchmarks that represent more functionality and different use
-  cases (in progress)
+  cases.
 
-## Contributors
+## Thanks
 
 Thanks to
 
 * Brandon Bloom for his advice.
 * Zach Tellman
 * Joel Holdbrooks for the ClojureScript version.
-* David Thomas Hume
-* Karsten Schmidt (CLJX restructure, cljc restructure, deftype impl & benchmark updates)
 
 ## License
 


=====================================
benchmarks/fast_zip/core_bench.clj
=====================================
@@ -8,32 +8,45 @@
 
 (def big-vec (vec (repeat 10 (vec (repeat 10 (vec (range 10)))))))
 
-(defn zip-walk
-  [zipper node next end?]
-  (loop [i 0, loc zipper]
-    (if (end? loc)
+(defn zip-test1
+  []
+  (loop [i 0, loc (z/vector-zip big-vec)]
+    (if (z/end? loc)
       i
-      (recur (long (if (integer? (node loc)) (unchecked-add-int i (node loc)) i)) (next loc)))))
+      (recur (long (if (integer? (z/node loc)) (unchecked-add-int i (z/node loc)) i)) (z/next loc)))))
 
-(defn zip-edit
-  [zipper root node edit next end?]
-  (loop [loc zipper]
-    (if (end? loc)
-      (root loc)
-      (recur (next (if (integer? (node loc)) (edit loc * 10) loc))))))
-
-(defgoal vector-zip-walk-bench "Benchmark vector zip walk.")
-
-(defcase vector-zip-walk-bench :clojure.zip
-  [] (zip-walk (z/vector-zip big-vec) z/node z/next z/end?))
-
-(defcase vector-zip-walk-bench :fast-zip
-  [] (zip-walk (fz/vector-zip big-vec) fz/node fz/next fz/end?))
-
-(defgoal vector-zip-edit-bench "Benchmark vector zip edit.")
-
-(defcase vector-zip-edit-bench :clojure.zip
-  [] (zip-edit (z/vector-zip big-vec) z/root z/node z/edit z/next z/end?))
-
-(defcase vector-zip-edit-bench :fast-zip
-  [] (zip-edit (fz/vector-zip big-vec) fz/root fz/node fz/edit fz/next fz/end?))
+(defn zip-test2
+  []
+  (loop [i 0, loc (fz/vector-zip big-vec)]
+    (if (fz/end? loc)
+      i
+      (recur (long (if (integer? (fz/node loc)) (unchecked-add-int i (fz/node loc)) i)) (fz/next loc)))))
+
+(defgoal vector-zip-bench "Benchmark vector zip.")
+
+(defcase vector-zip-bench :clojure.zip
+  [] (zip-test1))
+
+(defcase vector-zip-bench :fast-zip
+  [] (zip-test2))
+
+;; 0.3.0
+;Goal:  Benchmark vector zip.
+;-----
+;Case:  :clojure.zip
+;Evaluation count : 68400 in 60 samples of 1140 calls.
+;Execution time mean : 879.080906 µs
+;Execution time std-deviation : 11.090444 µs
+;Execution time lower quantile : 864.859649 µs ( 2.5%)
+;Execution time upper quantile : 907.783816 µs (97.5%)
+;
+;Found 3 outliers in 60 samples (5.0000 %)
+;low-severe	 3 (5.0000 %)
+;Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
+;
+;Case:  :fast-zip
+;Evaluation count : 226980 in 60 samples of 3783 calls.
+;Execution time mean : 259.947207 µs
+;Execution time std-deviation : 3.051484 µs
+;Execution time lower quantile : 255.424266 µs ( 2.5%)
+;Execution time upper quantile : 266.486446 µs (97.5%)
\ No newline at end of file


=====================================
benchmarks/fast_zip/core_bench.cljs
=====================================
@@ -1,67 +1,51 @@
 (ns fast-zip.core-bench
   (:require
-   [fast-zip.core :as fz]
-   [clojure.zip :as z]
-   [cljs.nodejs :as nodejs]))
+    [fast-zip.core :as fz]
+    [clojure.zip :as z]
+    [cljs.nodejs :as nodejs]))
 
 (def Benchmark
   (nodejs/require "benchmark"))
 
 (def big-vec (vec (repeat 10 (vec (repeat 10 (vec (range 10)))))))
 
-(defn zip-walk
-  [zipper node next end?]
-  (loop [i 0, loc zipper]
-    (if (end? loc)
+(defn zip-test1
+  []
+  (loop [i 0, loc (z/vector-zip big-vec)]
+    (if (z/end? loc)
       i
-      (recur (long (if (integer? (node loc)) (unchecked-add-int i (node loc)) i)) (next loc)))))
+      (recur (long (if (integer? (z/node loc)) (unchecked-add-int i (z/node loc)) i)) (z/next loc)))))
 
-(defn zip-edit
-  [zipper root node edit next end?]
-  (loop [loc zipper]
-    (if (end? loc)
-      (root loc)
-      (recur (next (if (integer? (node loc)) (edit loc * 10) loc))))))
+(defn zip-test2
+  []
+  (loop [i 0, loc (fz/vector-zip big-vec)]
+    (if (fz/end? loc)
+      i
+      (recur (long (if (integer? (fz/node loc)) (unchecked-add-int i (fz/node loc)) i)) (fz/next loc)))))
 
-(defn make-benchmark
-  [id clj fz]
+(def suite
   (.. (.Suite Benchmark)
-      (add (str ":clojure.zip." id) clj)
-      (add (str ":fast-zip." id) fz)
-      (on "cycle" (fn [e] (.log js/console (js/String (.-target e)))))
-      (on "complete"
-          (fn [e]
-            (this-as
-             *this*
-             (let [fastest (-> *this*
-                               (.filter "fastest")
-                               (.pluck "name")
-                               (aget 0))]
-               (.log js/console "Fastest is" fastest)))))))
-
-(def bench-walk
-  (make-benchmark
-   "walk"
-   #(zip-walk (z/vector-zip big-vec) z/node z/next z/end?)
-   #(zip-walk (fz/vector-zip big-vec) fz/node fz/next fz/end?)))
-
-(def bench-edit
-  (make-benchmark
-   "edit"
-   #(zip-edit (z/vector-zip big-vec) z/root z/node z/edit z/next z/end?)
-   #(zip-edit (fz/vector-zip big-vec) fz/root fz/node fz/edit fz/next fz/end?)))
-
-(defn main
-  []
-  (.log js/console "Benchmark: vector zip walk...")
-  (.run bench-walk)
-  (.log js/console "Benchmark: vector zip edit...")
-  (.run bench-edit)
+    (add ":clojure.zip" zip-test1)
+    (add ":fast-zip" zip-test2)
+    (on "cycle"
+      (fn [e]
+        (.log js/console (js/String (.-target e)))))
+    (on "complete"
+      (fn [e]
+        (this-as *this*
+          (let [fastest (-> *this*
+                          (.filter "fastest")
+                          (.pluck "name")
+                          (aget 0))]
+            (.log js/console "Fastest is" fastest)))))))
+
+(do
+  (.log js/console "Benchmark vector zip.")
+  (.run suite)
   (.exit js/process))
 
-(set! *main-cli-fn* main)
-
 ;; Benchmark vector zip.
 ;; :clojure.zip x 95.20 ops/sec ±1.75% (81 runs sampled)
 ;; :fast-zip x 222 ops/sec ±0.88% (90 runs sampled)
 ;; Fastest is :fast-zip
+


=====================================
project.clj
=====================================
@@ -1,33 +1,44 @@
-(defproject fast-zip "0.7.0"
+(defproject fast-zip "0.5.0"
   :description "A modification of clojure.zip that uses protocols and records."
   :url "https://github.com/akhudek/fast-zip"
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
 
-  :dependencies [[org.clojure/clojure "1.7.0" :scope "provided"]
-                 [org.clojure/clojurescript "1.7.107" :scope "provided"]]
+  :dependencies [[org.clojure/clojure "1.6.0" :scope "provided"]
+                 [org.clojure/clojurescript "0.0-2311" :scope "provided"]]
+
+  :plugins [[perforate "0.3.2"]
+            [lein-cljsbuild "1.0.3"]
+            [com.cemerick/clojurescript.test "0.3.1"]]
+
+  :source-paths
+  ["src/clj" "src/cljs"]
+
+  :test-paths
+  ["test/clj" "test/cljs"]
 
   ;; Prevent lein from disabling jvm optimizations.
-  :jvm-opts ^:replace []
+  :jvm-opts ^:replace ["-server"]
 
   :profiles {:dev
              {:dependencies
-              [[perforate "0.3.4"]
-               [criterium "0.4.3"]]
-              :plugins
-              [[perforate "0.3.4"]
-               [lein-npm "0.6.1"]
-               [lein-cljsbuild "1.0.6"]
-               [com.cemerick/clojurescript.test "0.3.3"]]
+              [[perforate "0.3.3"]
+               [criterium "0.4.3"]
+               [org.bodil/cljs-noderepl "0.1.11"]
+               [com.cemerick/piggieback "0.1.3"]]
               :node-dependencies
               [benchmark "1.0.0"]
+              :plugins
+              [[lein-npm "0.4.0"]
+               [com.cemerick/austin "0.1.5"]]
               :aliases
               {"clean-test" ~(clojure.string/split
-                              "do clean, test, cljsbuild test"
+                              "do test, cljsbuild clean, cljsbuild test"
                               #" ")
                "clean-bench" ~(clojure.string/split
-                               "do clean, cljsbuild once bench"
-                               #" ")}}}
+                               "do cljsbuild clean, cljsbuild once bench"
+                               #" ")}
+              :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}}}
 
   :perforate {:environments [{:namespaces [fast-zip.core-bench]}]}
 
@@ -39,12 +50,12 @@
 
   :cljsbuild
   {:builds [{:id "test"
-             :source-paths ["src" "test"]
+             :source-paths ["src/cljs" "test/cljs"]
              :compiler {:output-to "target/cljs/testable.js"
                         :optimizations :whitespace
                         :pretty-print true}}
             {:id "bench"
-             :source-paths ["src" "benchmarks"]
+             :source-paths ["src/cljs" "benchmarks"]
              :notify-command ["node" "target/cljs/benchmark.js"]
              :compiler {:target :nodejs
                         :output-to "target/cljs/benchmark.js"


=====================================
src/clj/fast_zip/core.clj
=====================================
@@ -0,0 +1,298 @@
+;   Copyright (c) Rich Hickey. All rights reserved.
+;   The use and distribution terms for this software are covered by the
+;   Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;   which can be found in the file epl-v10.html at the root of this distribution.
+;   By using this software in any fashion, you are agreeing to be bound by
+;   the terms of this license.
+;   You must not remove this notice, or any other, from this software.
+
+;functional hierarchical zipper, with navigation, editing and enumeration
+;see Huet
+
+(ns ^{:doc "Functional hierarchical zipper, with navigation, editing,
+  and enumeration.  See Huet"
+      :author "Rich Hickey, modified by Alexander K. Hudek"}
+  fast-zip.core
+  (:refer-clojure :exclude (replace remove next)))
+
+(defrecord ZipperPath [l r ppath pnodes changed?])
+
+(defrecord ZipperLocation [branch? children make-node node path])
+
+(defn zipper
+  "Creates a new zipper structure.
+
+  branch? is a fn that, given a node, returns true if can have
+  children, even if it currently doesn't.
+
+  children is a fn that, given a branch node, returns a seq of its
+  children.
+
+  make-node is a fn that, given an existing node and a seq of
+  children, returns a new branch node with the supplied children.
+  root is the root node."
+  {:added "1.0"}
+  [branch? children make-node root]
+  (ZipperLocation. branch? children make-node root nil))
+
+(defn seq-zip
+  "Returns a zipper for nested sequences, given a root sequence"
+  {:added "1.0"}
+  [root]
+  (zipper seq?
+    identity
+    (fn [node children] (with-meta children (meta node)))
+    root))
+
+(defn vector-zip
+  "Returns a zipper for nested vectors, given a root vector"
+  {:added "1.0"}
+  [root]
+  (zipper
+    vector?
+    seq
+    (fn [node children] (with-meta (vec children) (meta node)))
+    root))
+
+(defn xml-zip
+  "Returns a zipper for xml elements (as from xml/parse),
+  given a root element"
+  {:added "1.0"}
+  [root]
+  (zipper (complement string?)
+    (comp seq :content)
+    (fn [node children]
+      (assoc node :content (and children (apply vector children))))
+    root))
+
+(defn node
+  "Returns the node at loc"
+  [^ZipperLocation loc]
+  (.node loc))
+
+(defn branch?
+  "Returns true if the node at loc is a branch"
+  [^ZipperLocation loc]
+  ((.branch? loc) (.node loc)))
+
+(defn children
+  "Returns a seq of the children of node at loc, which must be a branch"
+  [^ZipperLocation loc]
+  ((.children loc) (.node loc)))
+
+(defn make-node
+  "Returns a new branch node, given an existing node and new children.
+  The loc is only used to supply the constructor."
+  [^ZipperLocation loc node children]
+  ((.make-node loc) node children))
+
+(defn path
+  "Returns a seq of nodes leading to this loc"
+  [^ZipperLocation loc]
+  (if-let [p (.path loc)] (.pnodes ^ZipperPath p)))
+
+(defn lefts
+  "Returns a seq of the left siblings of this loc"
+  [^ZipperLocation loc]
+  (if-let [p (.path loc)] (seq (reverse (.l ^ZipperPath p)))))
+
+(defn rights
+  "Returns a seq of the right siblings of this loc"
+  [^ZipperLocation loc]
+  (if-let [p (.path loc)] (.r ^ZipperPath p)))
+
+(defn down
+  "Returns the loc of the leftmost child of the node at this loc,
+  or nil if no children"
+  [^ZipperLocation loc]
+  (when (branch? loc)
+    (when-let [cs (children loc)]
+      (let [node (.node loc), path ^ZipperPath (.path loc)]
+        (ZipperLocation.
+          (.branch? loc)
+          (.children loc)
+          (.make-node loc)
+          (first cs)
+          (ZipperPath. '() (clojure.core/next cs) path (if path (conj (.pnodes path) node) [node]) nil))))))
+
+(defn up
+  "Returns the loc of the parent of the node at this loc, or nil if at the top"
+  [^ZipperLocation loc]
+  (let [node (.node loc), path ^ZipperPath (.path loc)]
+    (when-let [pnodes (and path (.pnodes path))]
+      (let [pnode (peek pnodes)]
+        (if (.changed? path)
+          (ZipperLocation.
+            (.branch? loc)
+            (.children loc)
+            (.make-node loc)
+            (make-node loc pnode (concat (reverse (.l path)) (cons node (.r path))))
+            (if-let [ppath (.ppath path)] (assoc ppath :changed? true)))
+          (ZipperLocation.
+            (.branch? loc)
+            (.children loc)
+            (.make-node loc)
+            pnode
+            (.ppath path)))))))
+
+(defn root
+  "zips all the way up and returns the root node, reflecting any changes."
+  [^ZipperLocation loc]
+  (if (identical? :end (.path loc))
+    (.node loc)
+    (let [p (up loc)]
+      (if p
+        (recur p)
+        (.node loc)))))
+
+(defn right
+  "Returns the loc of the right sibling of the node at this loc, or nil"
+  [^ZipperLocation loc]
+  (let [path ^ZipperPath (.path loc)]
+    (when-let [r (and path (.r path))]
+      (ZipperLocation.
+        (.branch? loc)
+        (.children loc)
+        (.make-node loc)
+        (first r)
+        (assoc path :l (conj (.l path) (.node loc)) :r (clojure.core/next r))))))
+
+(defn rightmost
+  "Returns the loc of the rightmost sibling of the node at this loc, or self"
+  [^ZipperLocation loc]
+  (let [path ^ZipperPath (.path loc)]
+    (if-let [r (and path (.r path))]
+      (ZipperLocation.
+        (.branch? loc)
+        (.children loc)
+        (.make-node loc)
+        (last r)
+        (assoc path :l (apply conj (.l path) (.node loc) (butlast r)) :r nil))
+      loc)))
+
+(defn left
+  "Returns the loc of the left sibling of the node at this loc, or nil"
+  [^ZipperLocation loc]
+  (let [path ^ZipperPath (.path loc)]
+    (when (and path (seq (.l path)))
+      (ZipperLocation.
+        (.branch? loc)
+        (.children loc)
+        (.make-node loc)
+        (peek (.l path))
+        (assoc path :l (pop (.l path)) :r (cons (.node loc) (.r path)))))))
+
+(defn leftmost
+  "Returns the loc of the leftmost sibling of the node at this loc, or self"
+  [^ZipperLocation loc]
+  (let [path ^ZipperPath (.path loc)]
+    (if (and path (seq (.l path)))
+      (ZipperLocation.
+        (.branch? loc)
+        (.children loc)
+        (.make-node loc)
+        (peek (.l path))
+        (assoc path :l [] :r (concat (clojure.core/next (reverse (.l path))) [(.node loc)] (.r path))))
+      loc)))
+
+(defn insert-left
+  "Inserts the item as the left sibling of the node at this loc, without moving"
+  [^ZipperLocation loc item]
+  (if-let [path ^ZipperPath (.path loc)]
+    (ZipperLocation.
+      (.branch? loc)
+      (.children loc)
+      (.make-node loc)
+      (.node loc)
+      (assoc path :l (conj (.l path) item) :changed? true))
+    (throw (new Exception "Insert at top"))))
+
+(defn insert-right
+  "Inserts the item as the right sibling of the node at this loc, without moving"
+  [^ZipperLocation loc item]
+  (if-let [path ^ZipperPath (.path loc)]
+    (ZipperLocation.
+      (.branch? loc)
+      (.children loc)
+      (.make-node loc)
+      (.node loc)
+      (assoc path :r (cons item (.r path)) :changed? true))
+    (throw (new Exception "Insert at top"))))
+
+(defn replace
+  "Replaces the node at this loc, without moving"
+  [^ZipperLocation loc node]
+  (ZipperLocation.
+    (.branch? loc)
+    (.children loc)
+    (.make-node loc)
+    node
+    (if-let [path (.path loc)] (assoc path :changed? true))))
+
+(defn insert-child
+  "Inserts the item as the leftmost child of the node at this loc, without moving"
+  [^ZipperLocation loc item]
+  (replace loc (make-node loc (.node loc) (cons item (children loc)))))
+
+(defn append-child
+  "Inserts the item as the rightmost child of the node at this loc, without moving"
+  [^ZipperLocation loc item]
+  (replace loc (make-node loc (.node loc) (concat (children loc) [item]))))
+
+(defn next
+  "Moves to the next loc in the hierarchy, depth-first. When reaching
+  the end, returns a distinguished loc detectable via end?. If already
+  at the end, stays there."
+  [^ZipperLocation loc]
+  (let [path (.path loc)]
+    (if (identical? :end path)
+      loc
+      (or
+        (and (branch? loc) (down loc))
+        (right loc)
+         (loop [p loc]
+           (if (up p)
+            (or (right (up p)) (recur (up p)))
+            (ZipperLocation. (.branch? loc) (.children loc) (.make-node loc) (.node p) :end)))))))
+
+(defn prev
+  "Moves to the previous loc in the hierarchy, depth-first. If already at the root, returns nil."
+  [loc]
+  (if-let [lloc (left loc)]
+    (loop [loc lloc]
+      (if-let [child (and (branch? loc) (down loc))]
+        (recur (rightmost child))
+        loc))
+    (up loc)))
+
+(defn end?
+  "Returns true if loc represents the end of a depth-first walk"
+  [^ZipperLocation loc]
+  (identical? :end (.path loc)))
+
+(defn remove
+  "Removes the node at loc, returning the loc that would have preceded it in a depth-first walk."
+  [^ZipperLocation loc]
+  (if-let [path ^ZipperPath (.path loc)]
+    (if (pos? (count (.l path)))
+      (loop [loc (ZipperLocation.
+                   (.branch? loc)
+                   (.children loc)
+                   (.make-node loc)
+                   (peek (.l path))
+                   (assoc path :l (pop (.l path)) :changed? true))]
+        (if-let [child (and (branch? loc) (down loc))]
+          (recur (rightmost child))
+          loc))
+      (ZipperLocation.
+        (.branch? loc)
+        (.children loc)
+        (.make-node loc)
+        (make-node loc (peek (.pnodes path)) (.r path))
+        (if-let [ppath (.ppath path)] (and ppath (assoc ppath :changed? true)))))
+    (throw (new Exception "Remove at top"))))
+
+(defn edit
+  "Replaces the node at this loc with the value of (f node args)"
+  [^ZipperLocation loc f & args]
+  (replace loc (apply f (.node loc) args)))


=====================================
src/fast_zip/core.cljc → src/cljs/fast_zip/core.cljs
=====================================
@@ -1,13 +1,13 @@
-;;   Copyright (c) Rich Hickey. All rights reserved.
-;;   The use and distribution terms for this software are covered by the
-;;   Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
-;;   which can be found in the file epl-v10.html at the root of this distribution.
-;;   By using this software in any fashion, you are agreeing to be bound by
-;;   the terms of this license.
-;;   You must not remove this notice, or any other, from this software.
+;   Copyright (c) Rich Hickey. All rights reserved.
+;   The use and distribution terms for this software are covered by the
+;   Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;   which can be found in the file epl-v10.html at the root of this distribution.
+;   By using this software in any fashion, you are agreeing to be bound by
+;   the terms of this license.
+;   You must not remove this notice, or any other, from this software.
 
-;;   functional hierarchical zipper, with navigation, editing and enumeration
-;;   see Huet
+;functional hierarchical zipper, with navigation, editing and enumeration
+;see Huet
 
 (ns ^{:doc "Functional hierarchical zipper, with navigation, editing,
   and enumeration.  See Huet"
@@ -15,11 +15,9 @@
   fast-zip.core
   (:refer-clojure :exclude [replace remove next]))
 
-(deftype ZipperOps [branch? children make-node])
+(defrecord ZipperPath [l r ppath pnodes changed?])
 
-(deftype ZipperPath [l r ppath pnodes changed?])
-
-(deftype ZipperLocation [^ZipperOps ops node ^ZipperPath path])
+(defrecord ZipperLocation [branch? children make-node node path])
 
 (defn zipper
   "Creates a new zipper structure.
@@ -35,39 +33,37 @@
   root is the root node."
   {:added "1.0"}
   [branch? children make-node root]
-  (ZipperLocation. (ZipperOps. branch? children make-node) root nil))
+  (ZipperLocation. branch? children make-node root nil))
 
 (defn seq-zip
   "Returns a zipper for nested sequences, given a root sequence"
   {:added "1.0"}
   [root]
-  (zipper
-   seq?
-   identity
-   (fn [node children] (with-meta children (meta node)))
-   root))
+  (zipper seq?
+    identity
+    (fn [node children] (with-meta children (meta node)))
+    root))
 
 (defn vector-zip
   "Returns a zipper for nested vectors, given a root vector"
   {:added "1.0"}
   [root]
   (zipper
-   vector?
-   seq
-   (fn [node children] (with-meta (vec children) (meta node)))
-   root))
+    vector?
+    seq
+    (fn [node children] (with-meta (vec children) (meta node)))
+    root))
 
 (defn xml-zip
   "Returns a zipper for xml elements (as from xml/parse),
   given a root element"
   {:added "1.0"}
   [root]
-  (zipper
-   (complement string?)
-   (comp seq :content)
-   (fn [node children]
-     (assoc node :content (and children (apply vector children))))
-   root))
+  (zipper (complement string?)
+    (comp seq :content)
+    (fn [node children]
+      (assoc node :content (and children (apply vector children))))
+    root))
 
 (defn node
   "Returns the node at loc"
@@ -77,33 +73,33 @@
 (defn branch?
   "Returns true if the node at loc is a branch"
   [^ZipperLocation loc]
-  ((.-branch? ^ZipperOps (.-ops loc)) (.-node loc)))
+  ((.-branch? loc) (.-node loc)))
 
 (defn children
   "Returns a seq of the children of node at loc, which must be a branch"
   [^ZipperLocation loc]
-  ((.-children ^ZipperOps (.-ops loc)) (.-node loc)))
+  ((.-children loc) (.-node loc)))
 
 (defn make-node
   "Returns a new branch node, given an existing node and new children.
   The loc is only used to supply the constructor."
   [^ZipperLocation loc node children]
-  ((.-make-node ^ZipperOps (.-ops loc)) node children))
+  ((.-make-node loc) node children))
 
 (defn path
   "Returns a seq of nodes leading to this loc"
   [^ZipperLocation loc]
-  (if-let [^ZipperPath p (.-path loc)] (.-pnodes p)))
+  (if-let [p (.-path loc)] (.-pnodes ^ZipperPath p)))
 
 (defn lefts
   "Returns a seq of the left siblings of this loc"
   [^ZipperLocation loc]
-  (if-let [^ZipperPath p (.-path loc)] (seq (reverse (.-l p)))))
+  (if-let [p (.-path loc)] (seq (reverse (.-l ^ZipperPath p)))))
 
 (defn rights
   "Returns a seq of the right siblings of this loc"
   [^ZipperLocation loc]
-  (if-let [^ZipperPath p (.-path loc)] (.-r p)))
+  (if-let [p (.-path loc)] (.-r ^ZipperPath p)))
 
 (defn down
   "Returns the loc of the leftmost child of the node at this loc,
@@ -111,38 +107,38 @@
   [^ZipperLocation loc]
   (when (branch? loc)
     (when-let [cs (children loc)]
-      (let [node (.-node loc), ^ZipperPath path (.-path loc)]
+      (let [node (.-node loc), path ^ZipperPath (.-path loc)]
         (ZipperLocation.
-         (.-ops loc)
-         (first cs)
-         (ZipperPath.
-          '()
-          #?(:clj (.next ^clojure.lang.ISeq cs) :cljs (cljs.core/next cs))
-          path
-          (if path (conj (.-pnodes path) node) [node])
-          nil))))))
+          (.-branch? loc)
+          (.-children loc)
+          (.-make-node loc)
+          (first cs)
+          (ZipperPath. '() (clojure.core/next cs) path (if path (conj (.-pnodes path) node) [node]) nil))))))
 
 (defn up
   "Returns the loc of the parent of the node at this loc, or nil if at the top"
   [^ZipperLocation loc]
-  (let [^ZipperPath path (.-path loc)]
+  (let [node (.-node loc), path ^ZipperPath (.-path loc)]
     (when-let [pnodes (and path (.-pnodes path))]
       (let [pnode (peek pnodes)]
         (if (.-changed? path)
           (ZipperLocation.
-           (.-ops loc)
-           (make-node loc pnode (concat (reverse (.-l path)) (cons (.-node loc) (.-r path))))
-           (if-let [^ZipperPath ppath (.-ppath path)]
-             (ZipperPath. (.-l ppath) (.-r ppath) (.-ppath ppath) (.-pnodes ppath) true)))
+            (.-branch? loc)
+            (.-children loc)
+            (.-make-node loc)
+            (make-node loc pnode (concat (reverse (.-l path)) (cons node (.-r path))))
+            (if-let [ppath (.-ppath path)] (assoc ppath :changed? true)))
           (ZipperLocation.
-           (.-ops loc)
-           pnode
-           (.-ppath path)))))))
+            (.-branch? loc)
+            (.-children loc)
+            (.-make-node loc)
+            pnode
+            (.-ppath path)))))))
 
 (defn root
   "zips all the way up and returns the root node, reflecting any changes."
   [^ZipperLocation loc]
-  (if (#?(:clj identical? :cljs =) :end (.-path loc))
+  (if (= :end (.-path loc))
     (.-node loc)
     (let [p (up loc)]
       (if p
@@ -152,96 +148,86 @@
 (defn right
   "Returns the loc of the right sibling of the node at this loc, or nil"
   [^ZipperLocation loc]
-  (let [^ZipperPath path (.-path loc)]
+  (let [path ^ZipperPath (.-path loc)]
     (when-let [r (and path (.-r path))]
       (ZipperLocation.
-       (.-ops loc)
-       (first r)
-       (ZipperPath.
-        (conj (.-l path) (.-node loc))
-        #?(:clj (.next ^clojure.lang.ISeq r) :cljs (cljs.core/next r))
-        (.-ppath path)
-        (.-pnodes path)
-        (.-changed? path))))))
+        (.-branch? loc)
+        (.-children loc)
+        (.-make-node loc)
+        (first r)
+        (assoc path :l (conj (.-l path) (.-node loc)) :r (clojure.core/next r))))))
 
 (defn rightmost
   "Returns the loc of the rightmost sibling of the node at this loc, or self"
   [^ZipperLocation loc]
-  (let [^ZipperPath path (.-path loc)]
+  (let [path ^ZipperPath (.-path loc)]
     (if-let [r (and path (.-r path))]
       (ZipperLocation.
-       (.-ops loc)
-       (last r)
-       (ZipperPath.
-        (apply conj (.-l path) (.-node loc) (butlast r))
-        nil
-        (.-ppath path)
-        (.-pnodes path)
-        (.-changed? path)))
+        (.-branch? loc)
+        (.-children loc)
+        (.-make-node loc)
+        (last r)
+        (assoc path :l (apply conj (.-l path) (.-node loc) (butlast r)) :r nil))
       loc)))
 
 (defn left
   "Returns the loc of the left sibling of the node at this loc, or nil"
   [^ZipperLocation loc]
-  (let [^ZipperPath path (.-path loc)]
+  (let [path ^ZipperPath (.-path loc)]
     (when (and path (seq (.-l path)))
       (ZipperLocation.
-       (.-ops loc)
-       (peek (.-l path))
-       (ZipperPath.
-        (pop (.-l path))
-        (cons (.-node loc) (.-r path))
-        (.-ppath path)
-        (.-pnodes path)
-        (.-changed? path))))))
+        (.-branch? loc)
+        (.-children loc)
+        (.-make-node loc)
+        (peek (.-l path))
+        (assoc path :l (pop (.-l path)) :r (cons (.-node loc) (.-r path)))))))
 
 (defn leftmost
   "Returns the loc of the leftmost sibling of the node at this loc, or self"
   [^ZipperLocation loc]
-  (let [^ZipperPath path (.-path loc)]
+  (let [path ^ZipperPath (.-path loc)]
     (if (and path (seq (.-l path)))
       (ZipperLocation.
-       (.-ops loc)
-       (last (.-l path))
-       (ZipperPath.
-        '()
-        (concat
-         #?(:clj (.next ^clojure.lang.ISeq (reverse (.-l path)))
-            :cljs (cljs.core/next (reverse (.-l path))))
-         [(.-node loc)] (.-r path))
-        (.-ppath path)
-        (.-pnodes path)
-        (.-changed? path)))
+        (.-branch? loc)
+        (.-children loc)
+        (.-make-node loc)
+        (peek (.-l path))
+        (assoc path :l [] :r (concat (clojure.core/next (reverse (.-l path))) [(.-node loc)] (.-r path))))
       loc)))
 
 (defn insert-left
   "Inserts the item as the left sibling of the node at this loc, without moving"
   [^ZipperLocation loc item]
-  (if-let [^ZipperPath path (.-path loc)]
+  (if-let [path ^ZipperPath (.-path loc)]
     (ZipperLocation.
-     (.-ops loc)
-     (.-node loc)
-     (ZipperPath. (conj (.-l path) item) (.-r path) (.-ppath path) (.-pnodes path) true))
-    (throw (new #?(:clj Exception :cljs js/Error) "Insert at top"))))
+      (.-branch? loc)
+      (.-children loc)
+      (.-make-node loc)
+      (.-node loc)
+      (assoc path :l (conj (.-l path) item) :changed? true))
+    (throw (new js/Error "Insert at top"))))
 
 (defn insert-right
   "Inserts the item as the right sibling of the node at this loc, without moving"
   [^ZipperLocation loc item]
-  (if-let [^ZipperPath path (.-path loc)]
+  (if-let [path ^ZipperPath (.-path loc)]
     (ZipperLocation.
-     (.-ops loc)
-     (.-node loc)
-     (ZipperPath. (.-l path) (cons item (.-r path)) (.-ppath path) (.-pnodes path) true))
-    (throw (new #?(:clj Exception :cljs js/Error) "Insert at top"))))
+      (.-branch? loc)
+      (.-children loc)
+      (.-make-node loc)
+      (.-node loc)
+      (assoc path :r (cons item (.-r path)) :changed? true))
+    (throw (new js/Error "Insert at top"))))
 
 (defn replace
   "Replaces the node at this loc, without moving"
   [^ZipperLocation loc node]
   (ZipperLocation.
-   (.-ops loc)
-   node
-   (if-let [^ZipperPath path (.-path loc)]
-     (ZipperPath. (.-l path) (.-r path) (.-ppath path) (.-pnodes path) true))))
+    (.-branch? loc)
+    (.-children loc)
+    (.-make-node loc)
+    node
+    (if-let [path (.-path loc)] (assoc path :changed? true))))
 
 (defn insert-child
   "Inserts the item as the leftmost child of the node at this loc, without moving"
@@ -259,15 +245,15 @@
   at the end, stays there."
   [^ZipperLocation loc]
   (let [path (.-path loc)]
-    (if (#?(:clj identical? :cljs =) :end path)
+    (if (= :end path)
       loc
       (or
-       (if (branch? loc) (down loc))
-       (right loc)
-       (loop [p loc]
-         (if-let [u (up p)]
-           (or (right u) (recur u))
-           (ZipperLocation. (.-ops loc) (.-node p) :end)))))))
+        (and (branch? loc) (down loc))
+        (right loc)
+         (loop [p loc]
+           (if (up p)
+            (or (right (up p)) (recur (up p)))
+            (ZipperLocation. (.-branch? loc) (.-children loc) (.-make-node loc) (.-node p) :end)))))))
 
 (defn prev
   "Moves to the previous loc in the hierarchy, depth-first. If already at the root, returns nil."
@@ -282,26 +268,29 @@
 (defn end?
   "Returns true if loc represents the end of a depth-first walk"
   [^ZipperLocation loc]
-  (#?(:clj identical? :cljs =) :end (.-path loc)))
+  (= :end (.-path loc)))
 
 (defn remove
   "Removes the node at loc, returning the loc that would have preceded it in a depth-first walk."
   [^ZipperLocation loc]
-  (if-let [^ZipperPath path (.-path loc)]
+  (if-let [path ^ZipperPath (.-path loc)]
     (if (pos? (count (.-l path)))
       (loop [loc (ZipperLocation.
-                  (.-ops loc)
-                  (peek (.-l path))
-                  (ZipperPath. (pop (.-l path)) (.-r path) (.-ppath path) (.-pnodes path) true))]
+                   (.-branch? loc)
+                   (.-children loc)
+                   (.-make-node loc)
+                   (peek (.-l path))
+                   (assoc path :l (pop (.-l path)) :changed? true))]
         (if-let [child (and (branch? loc) (down loc))]
           (recur (rightmost child))
           loc))
       (ZipperLocation.
-       (.-ops loc)
-       (make-node loc (peek (.-pnodes path)) (.-r path))
-       (if-let [^ZipperPath ppath (.-ppath path)]
-         (if ppath (ZipperPath. (.-l ppath) (.-r ppath) (.-ppath ppath) (.-pnodes ppath) true)))))
-    (throw (new #?(:clj Exception :cljs js/Error) "Remove at top"))))
+        (.-branch? loc)
+        (.-children loc)
+        (.-make-node loc)
+        (make-node loc (peek (.-pnodes path)) (.-r path))
+        (if-let [ppath (.-ppath path)] (and ppath (assoc ppath :changed? true)))))
+    (throw (new js/Error "Remove at top"))))
 
 (defn edit
   "Replaces the node at this loc with the value of (f node args)"


=====================================
test/fast_zip/core_test.cljc → test/clj/fast_zip/core_test.clj
=====================================
@@ -1,7 +1,6 @@
 (ns fast-zip.core-test
   (:require
-   #?(:clj [clojure.test :refer :all]
-      :cljs [cemerick.cljs.test :refer-macros [deftest testing is]])
+    [clojure.test :refer :all]
     [fast-zip.core :as z]))
 
 (def data '[[a * b] + [c * d]])
@@ -40,9 +39,7 @@
     (is (= (-> dz z/down z/rightmost z/lefts)
            '([a * b] +)))
     (is (= (-> dz z/down z/right z/right z/leftmost z/rights)
-           '(+ [c * d])))
-    (is (= (-> (z/seq-zip '(a b c d)) z/down z/right z/right z/leftmost z/node)
-           'a)))
+           '(+ [c * d]))))
 
   (testing "Edits"
     (is (= (-> dz z/down z/right z/right z/down z/right (z/replace '/) z/root)


=====================================
test/cljs/fast_zip/core_test.cljs
=====================================
@@ -0,0 +1,73 @@
+(ns fast-zip.core-test
+  (:require
+   [cemerick.cljs.test :as t]
+   [fast-zip.core :as z])
+  (:require-macros
+   [cemerick.cljs.test :refer [deftest testing is]]))
+
+(def data '[[a * b] + [c * d]])
+(def dz (z/vector-zip data))
+
+(deftest zipper-tests
+  (testing "Edge cases"
+    (let [ez (z/seq-zip [])]
+      (is (nil? (z/path ez)))
+      (is (nil? (z/lefts ez)))
+      (is (nil? (z/rights ez)))
+      (is (nil? (z/down ez)))
+      (is (nil? (z/right ez)))
+      (is (nil? (z/left ez)))
+      (is (nil? (z/up ez)))
+      (is (= [] (z/node (z/seq-zip []))))
+      (is (= '() (z/node (z/seq-zip '()))))))
+
+  (testing "Basic navigation"
+    (is (= (z/node (z/right (z/down (z/right (z/right (z/down dz))))))
+          '* ))
+    (is (= (z/lefts (z/right (z/down (z/right (z/right (z/down dz))))))
+          '(c)))
+    (is (= (z/rights (z/right (z/down (z/right (z/right (z/down dz))))))
+          '(d)))
+    (is (= (z/node (z/up (z/up (z/right (z/down (z/right (z/right (z/down dz))))))))
+          data))
+    (is (= (z/path (z/right (z/down (z/right (z/right (z/down dz))))))
+          '[[[a * b] + [c * d]] [c * d]]))
+    (is (= (-> dz z/down z/right z/right z/down z/right z/node)
+          '*))
+    (is (= (-> dz z/down z/rights)
+           '(+ [c * d])))
+    (is (= (-> dz z/down z/right z/right z/lefts)
+           '([a * b] +)))
+    (is (= (-> dz z/down z/rightmost z/lefts)
+           '([a * b] +)))
+    (is (= (-> dz z/down z/right z/right z/leftmost z/rights)
+           '(+ [c * d]))))
+
+  (testing "Edits"
+    (is (= (-> dz z/down z/right z/right z/down z/right (z/replace '/) z/root)
+          '[[a * b] + [c / d]]))
+    (is (= (-> dz z/next z/next (z/edit str) z/next z/next z/next (z/replace '/) z/root)
+          '[["a" * b] / [c * d]]))
+    (is (= (-> dz z/next z/next z/next z/next z/next z/next z/next z/next z/next z/remove z/root)
+          '[[a * b] + [c *]]))
+    (is (= (-> dz z/next z/next z/next z/next z/next z/next z/next z/next z/next z/remove (z/insert-right 'e) z/root)
+          '[[a * b] + [c * e]]))
+    (is (= (-> dz z/next z/next z/next z/next z/next z/next z/next z/next z/next z/remove z/up (z/append-child 'e) z/root)
+          '[[a * b] + [c * e]]))
+    (is (z/end? (-> dz z/next z/next z/next z/next z/next z/next z/next z/next z/next z/remove z/next)))
+    (is (= (-> dz z/next z/remove z/next z/remove z/root)
+          '[[c * d]]))
+    (is (= '[[a / b] + [c / d]]
+          (loop [loc dz]
+            (if (z/end? loc)
+              (z/root loc)
+              (recur (z/next (if (= '* (z/node loc))
+                             (z/replace loc '/)
+                             loc)))))))
+    (is (= '[[a b] + [c d]]
+          (loop [loc dz]
+            (if (z/end? loc)
+              (z/root loc)
+              (recur (z/next (if (= '* (z/node loc))
+                             (z/remove loc)
+                             loc)))))))))



View it on GitLab: https://salsa.debian.org/clojure-team/fast-zip-clojure/-/commit/4399f948b03c5e623654404d904a9760117b6f38

-- 
View it on GitLab: https://salsa.debian.org/clojure-team/fast-zip-clojure/-/commit/4399f948b03c5e623654404d904a9760117b6f38
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20220709/2b60f7f9/attachment.htm>


More information about the pkg-java-commits mailing list