├── .gitignore
├── .travis.yml
├── README.md
├── project.clj
├── public
└── index.html
├── src
└── cljs
│ └── tailrecursion
│ └── priority_map.cljs
└── test
├── firefox-profile
└── user.js
├── run.sh
├── runner.js
└── tailrecursion
└── priority_map
└── test.cljs
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | /lib
3 | /classes
4 | /checkouts
5 | pom.xml
6 | *.jar
7 | *.class
8 | .lein-deps-sum
9 | .lein-failures
10 | .lein-plugins
11 | .lein-repl-history
12 | /public/test.js
13 | /test/firefox-profile
14 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: clojure
3 | lein: lein2
4 | script: lein2 cljsbuild once test && test/run.sh
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # cljs-priority-map [![Build Status][1]][2]
2 |
3 | This is a ClojureScript port of Mark Engelberg's [clojure.data.priority-map][3]
4 | for Clojure.
5 |
6 | A priority map is very similar to a sorted map, but whereas a sorted
7 | map produces a sequence of the entries sorted by key, a priority map
8 | produces the entries sorted by value.
9 |
10 | ## Usage
11 |
12 | ### Dependency
13 |
14 | Artifacts are published on [Clojars][4].
15 |
16 | ```clojure
17 | [tailrecursion/cljs-priority-map "1.2.1"]
18 | ```
19 |
20 | ```xml
21 |
22 | tailrecursion
23 | cljs-priority-map
24 | 1.2.1
25 |
26 | ```
27 |
28 | ### Example
29 |
30 | ```clojure
31 | ;; Require or use tailrecursion.priority-map in your namespace.
32 |
33 | (ns your-ns
34 | (:require [tailrecursion.priority-map :refer [priority-map priority-map-by]])))
35 |
36 | ;; The standard way to construct a priority map is with priority-map:
37 |
38 | (def p (priority-map :a 2 :b 1 :c 3 :d 5 :e 4 :f 3))
39 |
40 | p ;=> {:b 1, :a 2, :c 3, :f 3, :e 4, :d 5}
41 |
42 | ;; So :b has priority 1, :a has priority 2, and so on. Notice how the
43 | ;; priority map prints in an order sorted by its priorities (i.e., the
44 | ;; map's values)
45 |
46 | ;; We can use assoc to assign a priority to a new item:
47 |
48 | (assoc p :g 1) ;=> {:b 1, :g 1, :a 2, :c 3, :f 3, :e 4, :d 5}
49 |
50 | ;; or to assign a new priority to an extant item:
51 |
52 | (assoc p :c 4) ;=> {:b 1, :a 2, :f 3, :c 4, :e 4, :d 5}
53 |
54 | ;; We can remove an item from the priority map:
55 |
56 | (dissoc p :e) ;=> {:b 1, :a 2, :c 3, :f 3, :d 5}
57 |
58 | ;; An alternative way to add to the priority map is to conj a [item priority] pair:
59 |
60 | (conj p [:g 0]) ;=> {:g 0, :b 1, :a 2, :c 3, :f 3, :e 4, :d 5}
61 |
62 | (into p [[:g 0] [:h 1] [:i 2]]) ;=> {:g 0, :b 1, :h 1, :a 2, :i 2, :c 3, :f 3, :e 4, :d 5}
63 |
64 | ;; Priority maps are countable:
65 |
66 | (count p) ;=> 6
67 |
68 | ;; Like other maps, equivalence is based not on type, but on contents.
69 | ;; In other words, just as a sorted-map can be equal to a hash-map, so
70 | ;; can a priority-map.
71 |
72 | (= p {:b 1, :a 2, :c 3, :f 3, :e 4, :d 5}) ;=> true
73 |
74 | ;; You can test them for emptiness:
75 |
76 | (empty? (priority-map)) ;=> true
77 |
78 | (empty? p) ;=> false
79 |
80 | ;; You can test whether an item is in the priority map:
81 |
82 | (contains? p :a) ;=> true
83 |
84 | (contains? p :g) ;=> false
85 |
86 | ;; It is easy to look up the priority of a given item, using any of
87 | ;; the standard map mechanisms:
88 |
89 | (get p :a) ;=> 2
90 |
91 | (get p :g 10) ;=> 10
92 |
93 | (p :a) ;=> 2
94 |
95 | (:a p) ;=> 2
96 |
97 | ;; Priority maps derive much of their utility by providing priority-based
98 | ;; seq. Note that no guarantees are made about the order in which items
99 | ;; of the same priority appear.
100 |
101 | (seq p) ;=> ([:b 1] [:a 2] [:c 3] [:f 3] [:e 4] [:d 5])
102 |
103 | ;; Because no guarantees are made about the order of same-priority items,
104 | ;; note that rseq might not be an exact reverse of the seq. It is only
105 | ;; guaranteed to be in descending order.
106 |
107 | (rseq p) ;=> ([:d 5] [:e 4] [:c 3] [:f 3] [:a 2] [:b 1])
108 |
109 | ;; This means first/rest/next/for/map/etc. All operate in priority order.
110 |
111 | (first p) ;=> [:b 1]
112 |
113 | (rest p) ;=> ([:a 2] [:c 3] [:f 3] [:e 4] [:d 5])
114 |
115 | ;; This implementation supports subseq for obtaining sorted seqs of
116 | ;; entries for which one or two predicates are true.
117 |
118 | ;; seq of entries of priority > 3:
119 |
120 | (subseq p > 3) ;=> ([:e 4] [:d 5])
121 |
122 | ;; seq of entries of priority >= 3 but < 5:
123 |
124 | (subseq p >= 3 < 5) ;=> ([:c 3] [:f 3] [:e 4])
125 |
126 | ;; Priority maps support metadata:
127 |
128 | (meta (with-meta p {:extra :info})) ;=> {:extra :info}
129 |
130 | ;; But perhaps most importantly, priority maps can also function as
131 | ;; priority queues. peek, like first, gives you the first
132 | ;; [item priority] pair in the collection. pop removes the first
133 | ;; [item priority] from the collection. (Note that unlike rest, which
134 | ;; returns a seq, pop returns a priority map).
135 |
136 | (peek p) ;=> [:b 1]
137 |
138 | (pop p) ;=> {:a 2, :c 3, :f 3, :e 4, :d 5}
139 |
140 | ;; It is also possible to use a custom comparator:
141 |
142 | (priority-map-by > :a 1 :b 2 :c 3) ;=> {:c 3, :b 2, :a 1}
143 | ```
144 |
145 | ## Testing
146 |
147 | [PhantomJS](http://phantomjs.org/) is used for unit testing. With it
148 | installed, you can run the tests like so:
149 |
150 | lein cljsbuild test
151 |
152 | ## License
153 |
154 | Copyright © 2013 Alan Dipert
155 |
156 | Distributed under the Eclipse Public License, the same as Clojure.
157 |
158 | [1]: https://travis-ci.org/tailrecursion/cljs-priority-map.png?branch=master
159 | [2]: https://travis-ci.org/tailrecursion/cljs-priority-map
160 | [3]: https://github.com/clojure/data.priority-map
161 | [4]: https://clojars.org/tailrecursion/cljs-priority-map
162 |
--------------------------------------------------------------------------------
/project.clj:
--------------------------------------------------------------------------------
1 | (defproject tailrecursion/cljs-priority-map "1.2.1"
2 | :description "ClojureScript priority map implementation based on clojure.data.priority-map"
3 | :url "https://github.com/tailrecursion/cljs-priority-map"
4 | :license {:name "Eclipse Public License"
5 | :url "http://www.eclipse.org/legal/epl-v10.html"}
6 | :dependencies [[org.clojure/clojure "1.7.0"]
7 | [org.clojure/clojurescript "1.7.170"]]
8 | :source-paths ["src/cljs"]
9 | :plugins [[lein-cljsbuild "1.1.1"]]
10 | :cljsbuild {:builds {:test
11 | {:source-paths ["test"]
12 | :compiler {:output-to "public/test.js"
13 | :optimizations :advanced}
14 | :jar false}}
15 | :test-commands {"phantomjs" ["phantomjs" "public/test.js"]}})
16 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | priority-map test
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/cljs/tailrecursion/priority_map.cljs:
--------------------------------------------------------------------------------
1 | (ns tailrecursion.priority-map
2 | (:require [cljs.core :as core])
3 | (:use [cljs.reader :only [register-tag-parser!]])
4 | (:require-macros [cljs.core :as coreclj]))
5 |
6 | (deftype PersistentPriorityMap [priority->set-of-items item->priority meta keyfn ^:mutable __hash]
7 | IPrintWithWriter
8 | (-pr-writer [coll writer opts]
9 | (let [pr-pair (fn [keyval] (pr-sequential-writer writer pr-writer "" " " "" opts keyval))]
10 | (pr-sequential-writer writer pr-pair "#tailrecursion.priority-map {" ", " "}" opts coll)))
11 |
12 | IWithMeta
13 | (-with-meta [this meta]
14 | (PersistentPriorityMap. priority->set-of-items item->priority meta keyfn __hash))
15 |
16 | IMeta
17 | (-meta [this] meta)
18 |
19 | ICollection
20 | (-conj [this entry]
21 | (if (vector? entry)
22 | (-assoc this (-nth entry 0) (-nth entry 1))
23 | (reduce -conj this entry)))
24 |
25 | IEmptyableCollection
26 | (-empty [this] (with-meta
27 | tailrecursion.priority-map.PersistentPriorityMap.EMPTY
28 | meta))
29 |
30 | IEquiv
31 | (-equiv [this other]
32 | (-equiv item->priority other))
33 |
34 | IHash
35 | (-hash [this]
36 | (coreclj/caching-hash this core/hash-unordered-coll __hash))
37 |
38 | ISeqable
39 | (-seq [this]
40 | (if keyfn
41 | (seq (for [[priority item-set] priority->set-of-items, item item-set]
42 | [item (item->priority item)]))
43 | (seq (for [[priority item-set] priority->set-of-items, item item-set]
44 | [item priority]))))
45 |
46 | IReversible
47 | (-rseq [coll]
48 | (if keyfn
49 | (seq (for [[priority item-set] (rseq priority->set-of-items), item item-set]
50 | [item (item->priority item)]))
51 | (seq (for [[priority item-set] (rseq priority->set-of-items), item item-set]
52 | [item priority]))))
53 |
54 | ICounted
55 | (-count [this]
56 | (count item->priority))
57 |
58 | ILookup
59 | (-lookup [this item]
60 | (get item->priority item))
61 | (-lookup [coll item not-found]
62 | (get item->priority item not-found))
63 |
64 | IStack
65 | (-peek [this]
66 | (when-not (zero? (count item->priority))
67 | (let [f (first priority->set-of-items)
68 | item (first (val f))]
69 | (if keyfn
70 | [item (item->priority item)]
71 | [item (key f)]))))
72 | (-pop [this]
73 | (if (zero? (count item->priority))
74 | (throw (js/Error. "Can't pop empty priority map"))
75 | (let [f (first priority->set-of-items)
76 | item-set (val f)
77 | item (first item-set)
78 | priority-key (key f)]
79 | (if (= (count item-set) 1)
80 | (PersistentPriorityMap.
81 | (dissoc priority->set-of-items priority-key)
82 | (dissoc item->priority item)
83 | meta
84 | keyfn
85 | nil)
86 | (PersistentPriorityMap.
87 | (assoc priority->set-of-items priority-key (disj item-set item)),
88 | (dissoc item->priority item)
89 | meta
90 | keyfn
91 | nil)))))
92 |
93 | IAssociative
94 | (-assoc [this item priority]
95 | (if-let [current-priority (get item->priority item nil)]
96 | (if (= current-priority priority)
97 | this
98 | (let [priority-key (keyfn priority)
99 | current-priority-key (keyfn current-priority)
100 | item-set (get priority->set-of-items current-priority-key)]
101 | (if (= (count item-set) 1)
102 | (PersistentPriorityMap.
103 | (assoc (dissoc priority->set-of-items current-priority-key)
104 | priority-key (conj (get priority->set-of-items priority-key #{}) item))
105 | (assoc item->priority item priority)
106 | meta
107 | keyfn
108 | nil)
109 | (PersistentPriorityMap.
110 | (assoc priority->set-of-items
111 | current-priority-key (disj (get priority->set-of-items current-priority-key) item)
112 | priority-key (conj (get priority->set-of-items priority-key #{}) item))
113 | (assoc item->priority item priority)
114 | meta
115 | keyfn
116 | nil))))
117 | (let [priority-key (keyfn priority)]
118 | (PersistentPriorityMap.
119 | (assoc priority->set-of-items
120 | priority-key (conj (get priority->set-of-items priority-key #{}) item))
121 | (assoc item->priority item priority)
122 | meta
123 | keyfn
124 | nil))))
125 |
126 | (-contains-key? [this item]
127 | (contains? item->priority item))
128 |
129 | IMap
130 | (-dissoc [this item]
131 | (let [priority (item->priority item ::not-found)]
132 | (if (= priority ::not-found)
133 | this
134 | (let [priority-key (keyfn priority)
135 | item-set (priority->set-of-items priority-key)]
136 | (if (= (count item-set) 1)
137 | (PersistentPriorityMap.
138 | (dissoc priority->set-of-items priority-key)
139 | (dissoc item->priority item)
140 | meta
141 | keyfn
142 | nil)
143 | (PersistentPriorityMap.
144 | (assoc priority->set-of-items priority-key (disj item-set item)),
145 | (dissoc item->priority item)
146 | meta
147 | keyfn
148 | nil))))))
149 |
150 | ISorted
151 | (-sorted-seq [this ascending?]
152 | ((if ascending? seq rseq) this))
153 | (-sorted-seq-from [this k ascending?]
154 | (let [sets (if ascending?
155 | (subseq priority->set-of-items >= k)
156 | (rsubseq priority->set-of-items <= k))]
157 | (if keyfn
158 | (seq (for [[priority item-set] sets, item item-set]
159 | [item (item->priority item)]))
160 | (seq (for [[priority item-set] sets, item item-set]
161 | [item priority])))))
162 | (-entry-key [this entry]
163 | (keyfn (val entry)))
164 | (-comparator [this] compare)
165 |
166 | IFn
167 | (-invoke [this item]
168 | (-lookup this item))
169 | (-invoke [this item not-found]
170 | (-lookup this item not-found)))
171 |
172 | (set! tailrecursion.priority-map.PersistentPriorityMap.EMPTY
173 | (PersistentPriorityMap. (sorted-map) {} {} identity nil))
174 |
175 | (defn- pm-empty-by [comparator]
176 | (PersistentPriorityMap. (sorted-map-by comparator) {} {} identity nil))
177 |
178 | (defn- pm-empty-keyfn
179 | ([keyfn] (PersistentPriorityMap. (sorted-map) {} {} keyfn nil))
180 | ([keyfn comparator] (PersistentPriorityMap. (sorted-map-by comparator) {} {} keyfn nil)))
181 |
182 | (defn- read-priority-map [elems]
183 | (if (map? elems)
184 | (into tailrecursion.priority-map.PersistentPriorityMap.EMPTY elems)
185 | (throw (js/Error "Priority map literal expects a map for its elements."))))
186 |
187 | (register-tag-parser! "tailrecursion.priority-map" read-priority-map)
188 |
189 | (defn priority-map
190 | "keyval => key val
191 | Returns a new priority map with supplied mappings."
192 | ([& keyvals]
193 | (loop [in (seq keyvals) out tailrecursion.priority-map.PersistentPriorityMap.EMPTY]
194 | (if in
195 | (recur (nnext in) (assoc out (first in) (second in)))
196 | out))))
197 |
198 | (defn priority-map-by
199 | "keyval => key val
200 | Returns a new priority map with supplied
201 | mappings, using the supplied comparator."
202 | ([comparator & keyvals]
203 | (loop [in (seq keyvals) out (pm-empty-by comparator)]
204 | (if in
205 | (recur (nnext in) (assoc out (first in) (second in)))
206 | out))))
207 |
208 | (defn priority-map-keyfn
209 | "keyval => key val
210 | Returns a new priority map with supplied
211 | mappings, using the supplied keyfn."
212 | ([keyfn & keyvals]
213 | (loop [in (seq keyvals) out (pm-empty-keyfn keyfn)]
214 | (if in
215 | (recur (nnext in) (assoc out (first in) (second in)))
216 | out))))
217 |
218 | (defn priority-map-keyfn-by
219 | "keyval => key val
220 | Returns a new priority map with supplied
221 | mappings, using the supplied keyfn and comparator."
222 | ([keyfn comparator & keyvals]
223 | (loop [in (seq keyvals) out (pm-empty-keyfn keyfn comparator)]
224 | (if in
225 | (recur (nnext in) (assoc out (first in) (second in)))
226 | out))))
227 |
--------------------------------------------------------------------------------
/test/firefox-profile/user.js:
--------------------------------------------------------------------------------
1 | user_pref("browser.dom.window.dump.enabled", true);
2 | user_pref("dom.max_script_run_time", 9007199254740992);
3 |
--------------------------------------------------------------------------------
/test/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | run_phantom() {
6 | phantomjs --version
7 | phantomjs test/runner.js
8 | }
9 |
10 | run_ff() {
11 | firefox -version
12 | this_tty=$(tty)
13 | xvfb-run -a firefox -profile test/firefox-profile -no-remote "public/index.html" \
14 | | while read line; do
15 | if [ "$line" = "Done." ]; then
16 | kill -n 2 $(ps -t $this_tty | grep firefox | awk '{print $1}')
17 | echo "All tests passed (on firefox)."
18 | else
19 | echo "$line"
20 | fi
21 | done
22 | }
23 |
24 | run_phantom
25 | run_ff
26 |
--------------------------------------------------------------------------------
/test/runner.js:
--------------------------------------------------------------------------------
1 | function info(msg, type) {
2 | var red, green, reset;
3 | red = '\u001b[31m';
4 | green = '\u001b[32m';
5 | reset = '\u001b[0m';
6 | if(type == 'error') {
7 | console.error(red + msg + reset);
8 | } else {
9 | console.log(green + msg + reset);
10 | }
11 | }
12 |
13 | page = new WebPage();
14 |
15 | page.onConsoleMessage = info;
16 |
17 | page.onError = function(msg, trace) {
18 | var msgStack = ['ERROR: ' + msg];
19 | if (trace) {
20 | msgStack.push('TRACE:');
21 | trace.forEach(function(t) {
22 | msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function + '")' : ''));
23 | });
24 | }
25 | info(msgStack.join('\n'), 'error');
26 | phantom.exit(1);
27 | };
28 |
29 | page.onLoadFinished = function(status) {
30 | info("All tests passed (on phantomjs).");
31 | phantom.exit(0);
32 | };
33 |
34 | page.open("public/index.html");
35 |
--------------------------------------------------------------------------------
/test/tailrecursion/priority_map/test.cljs:
--------------------------------------------------------------------------------
1 | (ns tailrecursion.priority-map.test
2 | (:require [tailrecursion.priority-map :as pm]
3 | [cljs.reader :refer [read-string]]))
4 |
5 | (set! cljs.core/*print-fn*
6 | (if (undefined? (aget js/window "dump"))
7 | ;; phantomjs
8 | #(.apply (.-log js/console)
9 | (.-console js/window)
10 | (apply array %&))
11 | ;; firefox
12 | #(.apply (aget js/window "dump")
13 | js/window
14 | (apply array %&))))
15 |
16 | (def p (pm/priority-map :a 2 :b 1 :c 3 :d 5 :e 4 :f 3))
17 | (def h {:a 2 :b 1 :c 3 :d 5 :e 4 :f 3})
18 |
19 | (assert (= p {:a 2 :b 1 :c 3 :d 5 :e 4 :f 3}))
20 | (assert (= h p))
21 | (assert (= :b (first (peek (into (pm/priority-map) h)))))
22 | (assert (= (pm/priority-map 1 2) (pm/priority-map 1 2)))
23 | (assert (= (-hash p) (-hash {:a 2 :b 1 :c 3 :d 5 :e 4 :f 3})))
24 | (assert (= (assoc p :g 1) (assoc h :g 1)))
25 | (assert (= (assoc p :g 0) (assoc h :g 0)))
26 | (assert (= (assoc p :c 4) (assoc h :c 4)))
27 | (assert (= (assoc p :c 6) (assoc h :c 6)))
28 | (assert (= (assoc p :b 2) (assoc h :b 2)))
29 | (assert (= (assoc p :b 6) (assoc h :b 6)))
30 | (assert (= (dissoc p :e) (dissoc h :e)))
31 | (assert (= (dissoc p :g) (dissoc h :g)))
32 | (assert (= (dissoc p :c) (dissoc h :c)))
33 | (assert (= (dissoc p :x) p))
34 | (assert (= (peek (dissoc p :x)) (peek p)))
35 | (assert (= (pop (dissoc p :x)) (pop p)))
36 | (assert (= (conj p [:g 1]) (conj h [:g 1])))
37 | (assert (= (conj p [:g 0]) (conj h [:g 0])))
38 | (assert (= (conj p [:c 4]) (conj h [:c 4])))
39 | (assert (= (conj p [:c 6]) (conj h [:c 6])))
40 | (assert (= (conj p [:b 2]) (conj h [:b 2])))
41 | (assert (= (conj p [:b 6]) (conj h [:b 6])))
42 | (assert (= (into p [[:g 0] [:h 1] [:i 2]]) (into h [[:g 0] [:h 1] [:i 2]])))
43 | (assert (= (count p) (count h)))
44 | (assert (= (empty? p) false))
45 | (assert (= (empty? (pm/priority-map)) true))
46 | (assert (= (contains? p :a) true))
47 | (assert (= (contains? p :g) false))
48 | (assert (= (get p :a) 2))
49 | (assert (= (get p :a 8) 2))
50 | (assert (= (get p :g) nil))
51 | (assert (= (get p :g 8) 8))
52 | (assert (= (p :a) 2))
53 | (assert (= (:a p) 2))
54 | (assert (= (seq p) '([:b 1] [:a 2] [:c 3] [:f 3] [:e 4] [:d 5])))
55 | (assert (= (rseq p) '([:d 5] [:e 4] [:c 3] [:f 3] [:a 2] [:b 1])))
56 | (assert (= (first p) [:b 1]))
57 | (assert (= (rest p) '([:a 2] [:c 3] [:f 3] [:e 4] [:d 5])))
58 | (assert (= (meta (with-meta p {:extra :info})) {:extra :info}))
59 | (assert (= (meta (dissoc (with-meta p {:extra :info}) :a)) {:extra :info}))
60 | (assert (= (meta (assoc (with-meta p {:extra :info}) :g 0)) {:extra :info}))
61 | (assert (= (peek p) [:b 1]))
62 | (assert (= (pop p) {:a 2 :c 3 :f 3 :e 4 :d 5}))
63 | (assert (= (peek (pm/priority-map)) nil))
64 | (assert (= (seq (pm/priority-map-by > :a 1 :b 2 :c 3)) [[:c 3] [:b 2] [:a 1]]))
65 | (assert (= (meta (empty (with-meta p {:x 123}))) {:x 123}))
66 | (assert (= (subseq p < 3) '([:b 1] [:a 2])))
67 | (assert (= (subseq p >= 4) '([:e 4] [:d 5])))
68 | (assert (= (subseq p >= 4 < 5) '([:e 4])))
69 |
70 | (def pk (pm/priority-map-keyfn :order :a {:order 2} :b {:order 1} :c {:order 3}))
71 |
72 | (assert (= (seq pk) [[:b {:order 1}] [:a {:order 2}] [:c {:order 3}]]))
73 | (assert (= (subseq pk > 1) '([:a {:order 2}] [:c {:order 3}])))
74 | (assert (= (rsubseq pk < 3) '([:a {:order 2}] [:b {:order 1}])))
75 | (assert (assoc (pm/priority-map-keyfn first :a [1] :b [1]) :a [2]))
76 |
77 | (def pkb (pm/priority-map-keyfn-by :order > :a {:order 2} :b {:order 1} :c {:order 3}))
78 | (assert (= (seq pkb) [[:c {:order 3}] [:a {:order 2}] [:b {:order 1}]]))
79 | (assert (= (rsubseq pkb < 1) '([:a {:order 2}] [:c {:order 3}])))
80 | (assert (= (subseq pkb > 3) '([:a {:order 2}] [:b {:order 1}])))
81 |
82 | ;;; printing, reader
83 |
84 | (assert (= p (read-string (pr-str p))))
85 |
86 | ;;; perf
87 |
88 | (dotimes [_ 10]
89 | (time
90 | (loop [p2 (apply pm/priority-map (range 10000))]
91 | (when-not (empty? p2)
92 | (recur (pop p2))))))
93 |
94 | (dotimes [_ 10]
95 | (time
96 | (loop [p2 (apply pm/priority-map (range 10000))]
97 | (when-not (empty? p2)
98 | (peek p2)
99 | (recur (pop p2))))))
100 |
101 | ;; (def basis (atom 0))
102 |
103 | ;; (defn gstr []
104 | ;; (str "g__" (swap! basis inc)))
105 |
106 | ;; (defn bigmap [n]
107 | ;; (reduce merge
108 | ;; (take (* 100 n)
109 | ;; (repeatedly #(reduce
110 | ;; (fn [xs k] {k xs})
111 | ;; (take (* 10 n) (repeatedly gstr)))))))
112 |
113 | ;; (def bm1 (bigmap 3))
114 |
115 | ;; (reset! basis 0)
116 |
117 | ;; (def bm2 (bigmap 3))
118 |
119 | ;; (time
120 | ;; (dotimes [_ 10]
121 | ;; (println (= bm1 bm2))))
122 |
123 |
124 | (println "Done.")
125 |
--------------------------------------------------------------------------------