clementine 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. data/.gitignore +7 -0
  2. data/Gemfile +4 -0
  3. data/README.md +52 -0
  4. data/Rakefile +1 -0
  5. data/clementine.gemspec +23 -0
  6. data/lib/clementine.rb +27 -0
  7. data/lib/clementine/clementine_rails.rb +8 -0
  8. data/lib/clementine/clojurescript_engine.rb +49 -0
  9. data/lib/clementine/clojurescript_engine_mri.rb +65 -0
  10. data/lib/clementine/clojurescript_template.rb +21 -0
  11. data/lib/clementine/options.rb +9 -0
  12. data/lib/clementine/version.rb +3 -0
  13. data/test/clojurescript_engine_test.rb +46 -0
  14. data/test/options_test.rb +22 -0
  15. data/vendor/assets/bin/cljsc.clj +21 -0
  16. data/vendor/assets/lib/clojure.jar +0 -0
  17. data/vendor/assets/lib/compiler.jar +0 -0
  18. data/vendor/assets/lib/goog.jar +0 -0
  19. data/vendor/assets/lib/js.jar +0 -0
  20. data/vendor/assets/src/clj/cljs/closure.clj +823 -0
  21. data/vendor/assets/src/clj/cljs/compiler.clj +1341 -0
  22. data/vendor/assets/src/clj/cljs/core.clj +702 -0
  23. data/vendor/assets/src/clj/cljs/repl.clj +162 -0
  24. data/vendor/assets/src/clj/cljs/repl/browser.clj +341 -0
  25. data/vendor/assets/src/clj/cljs/repl/rhino.clj +170 -0
  26. data/vendor/assets/src/cljs/cljs/core.cljs +3330 -0
  27. data/vendor/assets/src/cljs/cljs/nodejs.cljs +11 -0
  28. data/vendor/assets/src/cljs/cljs/nodejs_externs.js +2 -0
  29. data/vendor/assets/src/cljs/cljs/nodejscli.cljs +9 -0
  30. data/vendor/assets/src/cljs/cljs/reader.cljs +360 -0
  31. data/vendor/assets/src/cljs/clojure/browser/dom.cljs +106 -0
  32. data/vendor/assets/src/cljs/clojure/browser/event.cljs +100 -0
  33. data/vendor/assets/src/cljs/clojure/browser/net.cljs +182 -0
  34. data/vendor/assets/src/cljs/clojure/browser/repl.cljs +109 -0
  35. data/vendor/assets/src/cljs/clojure/set.cljs +162 -0
  36. data/vendor/assets/src/cljs/clojure/string.cljs +160 -0
  37. data/vendor/assets/src/cljs/clojure/walk.cljs +94 -0
  38. data/vendor/assets/src/cljs/clojure/zip.cljs +291 -0
  39. metadata +103 -0
@@ -0,0 +1,170 @@
1
+ ;; Copyright (c) Rich Hickey. All rights reserved.
2
+ ;; The use and distribution terms for this software are covered by the
3
+ ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4
+ ;; which can be found in the file epl-v10.html at the root of this distribution.
5
+ ;; By using this software in any fashion, you are agreeing to be bound by
6
+ ;; the terms of this license.
7
+ ;; You must not remove this notice, or any other, from this software.
8
+
9
+ (ns cljs.repl.rhino
10
+ (:refer-clojure :exclude [loaded-libs])
11
+ (:require [clojure.string :as string]
12
+ [clojure.java.io :as io]
13
+ [cljs.compiler :as comp]
14
+ [cljs.repl :as repl])
15
+ (:import cljs.repl.IJavaScriptEnv
16
+ [org.mozilla.javascript Context ScriptableObject]))
17
+
18
+ (def current-repl-env (atom nil))
19
+ (def loaded-libs (atom #{}))
20
+
21
+ ;;todo - move to core.cljs, using js
22
+ (def ^String bootjs (str "goog.require = function(rule){"
23
+ "Packages.clojure.lang.RT[\"var\"](\"cljs.repl.rhino\",\"goog-require\")"
24
+ ".invoke(rule);}"))
25
+
26
+ (defprotocol IEval
27
+ (-eval [this env filename line]))
28
+
29
+ (extend-protocol IEval
30
+
31
+ java.lang.String
32
+ (-eval [this {:keys [cx scope]} filename line]
33
+ (.evaluateString cx scope this filename line nil))
34
+
35
+ java.io.Reader
36
+ (-eval [this {:keys [cx scope]} filename line]
37
+ (.evaluateReader cx scope this filename line nil))
38
+ )
39
+
40
+ (defmulti stacktrace class)
41
+
42
+ (defmethod stacktrace :default [e]
43
+ (apply str (interpose "\n" (map #(str " " (.toString %)) (.getStackTrace e)))))
44
+
45
+ (defmethod stacktrace org.mozilla.javascript.RhinoException [e]
46
+ (.getScriptStackTrace e))
47
+
48
+ (defmulti eval-result class)
49
+
50
+ (defmethod eval-result :default [r]
51
+ (.toString r))
52
+
53
+ (defmethod eval-result nil [_] "")
54
+
55
+ (defmethod eval-result org.mozilla.javascript.Undefined [_] "")
56
+
57
+ (defn rhino-eval
58
+ [repl-env filename line js]
59
+ (try
60
+ (let [linenum (or line Integer/MIN_VALUE)]
61
+ {:status :success
62
+ :value (eval-result (-eval js repl-env filename linenum))})
63
+ (catch Throwable ex
64
+ {:status :exception
65
+ :value (.toString ex)
66
+ :stacktrace (stacktrace ex)})))
67
+
68
+ (defn goog-require [rule]
69
+ (when-not (contains? @loaded-libs rule)
70
+ (let [repl-env @current-repl-env
71
+ path (string/replace (comp/munge rule) \. java.io.File/separatorChar)
72
+ cljs-path (str path ".cljs")
73
+ js-path (str "goog/"
74
+ (-eval (str "goog.dependencies_.nameToPath['" rule "']")
75
+ repl-env
76
+ "<cljs repl>"
77
+ 1))]
78
+ (if-let [res (io/resource cljs-path)]
79
+ (binding [comp/*cljs-ns* 'cljs.user]
80
+ (repl/load-stream repl-env res))
81
+ (if-let [res (io/resource js-path)]
82
+ (-eval (io/reader res) repl-env js-path 1)
83
+ (throw (Exception. (str "Cannot find " cljs-path " or " js-path " in classpath")))))
84
+ (swap! loaded-libs conj rule))))
85
+
86
+ (defn load-javascript [repl-env ns url]
87
+ (let [missing (remove #(contains? @loaded-libs %) ns)]
88
+ (when (seq missing)
89
+ (do (try
90
+ (-eval (io/reader url) repl-env (.toString url) 1)
91
+ ;; TODO: don't show errors for goog/base.js line number 105
92
+ (catch Throwable ex (println (.getMessage ex))))
93
+ (swap! loaded-libs (partial apply conj) missing)))))
94
+
95
+ (defn rhino-setup [repl-env]
96
+ (let [env {:context :statement :locals {} :ns (@comp/namespaces comp/*cljs-ns*)}
97
+ scope (:scope repl-env)]
98
+ (repl/load-file repl-env "cljs/core.cljs")
99
+ (swap! loaded-libs conj "cljs.core")
100
+ (repl/evaluate-form repl-env
101
+ env
102
+ "<cljs repl>"
103
+ '(ns cljs.user))
104
+ (ScriptableObject/putProperty scope
105
+ "out"
106
+ (Context/javaToJS System/out scope))
107
+ (repl/evaluate-form repl-env
108
+ env
109
+ "<cljs repl>"
110
+ '(set! *print-fn* (fn [x] (.print js/out x))))))
111
+
112
+ (extend-protocol repl/IJavaScriptEnv
113
+ clojure.lang.IPersistentMap
114
+ (-setup [this]
115
+ (rhino-setup this))
116
+ (-evaluate [this filename line js]
117
+ (rhino-eval this filename line js))
118
+ (-load [this ns url]
119
+ (load-javascript this ns url))
120
+ (-tear-down [_] (Context/exit)))
121
+
122
+ (defn repl-env
123
+ "Returns a fresh JS environment, suitable for passing to repl.
124
+ Hang on to return for use across repl calls."
125
+ []
126
+ (let [cx (Context/enter)
127
+ scope (.initStandardObjects cx)
128
+ base (io/resource "goog/base.js")
129
+ deps (io/resource "goog/deps.js")
130
+ new-repl-env {:cx cx :scope scope}]
131
+ (assert base "Can't find goog/base.js in classpath")
132
+ (assert deps "Can't find goog/deps.js in classpath")
133
+ (swap! current-repl-env (fn [old] new-repl-env))
134
+ (with-open [r (io/reader base)]
135
+ (-eval r new-repl-env "goog/base.js" 1))
136
+ (-eval bootjs new-repl-env "bootjs" 1)
137
+ ;; Load deps.js line-by-line to avoid 64K method limit
138
+ (doseq [^String line (line-seq (io/reader deps))]
139
+ (-eval line new-repl-env "goog/deps.js" 1))
140
+ new-repl-env))
141
+
142
+ (comment
143
+
144
+ (require '[cljs.repl :as repl])
145
+ (require '[cljs.repl.rhino :as rhino])
146
+ (def env (rhino/repl-env))
147
+ (repl/repl env)
148
+ (+ 1 1)
149
+ "hello"
150
+ {:a "hello"}
151
+ (:a {:a "hello"})
152
+ (:a {:a :b})
153
+ (reduce + [1 2 3 4 5])
154
+ (time (reduce + [1 2 3 4 5]))
155
+ (even? :a)
156
+ (throw (js/Error. "There was an error"))
157
+ (load-file "clojure/string.cljs")
158
+ (clojure.string/triml " hello")
159
+ (clojure.string/reverse " hello")
160
+
161
+ (load-namespace 'clojure.set)
162
+
163
+ (ns test.crypt
164
+ (:require [goog.crypt :as c]))
165
+ (c/stringToByteArray "Hello")
166
+
167
+ (load-namespace 'goog.date.Date)
168
+ (goog.date.Date.)
169
+
170
+ )
@@ -0,0 +1,3330 @@
1
+ ; Copyright (c) Rich Hickey. All rights reserved.
2
+ ; The use and distribution terms for this software are covered by the
3
+ ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4
+ ; which can be found in the file epl-v10.html at the root of this distribution.
5
+ ; By using this software in any fashion, you are agreeing to be bound by
6
+ ; the terms of this license.
7
+ ; You must not remove this notice, or any other, from this software.
8
+
9
+ (ns cljs.core
10
+ (:require [goog.string :as gstring]
11
+ [goog.string.StringBuffer :as gstringbuf]
12
+ [goog.object :as gobject]
13
+ [goog.array :as garray]))
14
+
15
+ (def
16
+ ^{:doc "Each runtime environment provides a diffenent way to print output.
17
+ Whatever function *print-fn* is bound to will be passed any
18
+ Strings which should be printed."}
19
+ *print-fn*
20
+ (fn [_]
21
+ (throw (js/Error. "No *print-fn* fn set for evaluation environment"))))
22
+
23
+ (def
24
+ ^{:doc "bound in a repl thread to the most recent value printed"}
25
+ *1)
26
+
27
+ (def
28
+ ^{:doc "bound in a repl thread to the second most recent value printed"}
29
+ *2)
30
+
31
+ (def
32
+ ^{:doc "bound in a repl thread to the third most recent value printed"}
33
+ *3)
34
+
35
+ (defn truth_
36
+ "Internal - do not use!"
37
+ [x]
38
+ (js* "(~{x} != null && ~{x} !== false)"))
39
+
40
+ (defn type_satisfies_
41
+ "Internal - do not use!"
42
+ [p x]
43
+ (or
44
+ (aget p (goog.typeOf x))
45
+ (aget p "_")
46
+ false))
47
+
48
+ (def
49
+ ^{:doc "When compiled for a command-line target, whatever
50
+ function *main-fn* is set to will be called with the command-line
51
+ argv as arguments"}
52
+ *main-cli-fn* nil)
53
+
54
+ (defn missing-protocol [proto obj]
55
+ (js/Error (js* "~{}+~{}+~{}+~{}+~{}+~{}"
56
+ "No protocol method " proto
57
+ " defined for type " (goog/typeOf obj) ": " obj)))
58
+
59
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; arrays ;;;;;;;;;;;;;;;;
60
+
61
+ (defn aclone
62
+ "Returns a javascript array, cloned from the passed in array"
63
+ [array-like]
64
+ #_(goog.array.clone array-like)
65
+ (js* "Array.prototype.slice.call(~{array-like})"))
66
+
67
+ (defn array
68
+ "Creates a new javascript array.
69
+ @param {...*} var_args" ;;array is a special case, don't emulate this doc string
70
+ [var-args] ;; [& items]
71
+ (js* "Array.prototype.slice.call(arguments)"))
72
+
73
+ (defn aget
74
+ "Returns the value at the index."
75
+ [array i]
76
+ (js* "~{array}[~{i}]"))
77
+
78
+ (defn aset
79
+ "Sets the value at the index."
80
+ [array i val]
81
+ (js* "(~{array}[~{i}] = ~{val})"))
82
+
83
+ (defn alength
84
+ "Returns the length of the Java array. Works on arrays of all types."
85
+ [array]
86
+ (js* "~{array}.length"))
87
+
88
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;; core protocols ;;;;;;;;;;;;;
89
+ (defprotocol ICounted
90
+ (-count [coll] "constant time count"))
91
+
92
+ (defprotocol IEmptyableCollection
93
+ (-empty [coll]))
94
+
95
+ (defprotocol ICollection
96
+ (-conj [coll o]))
97
+
98
+ #_(defprotocol IOrdinal
99
+ (-index [coll]))
100
+
101
+ (defprotocol IIndexed
102
+ (-nth [coll n] [coll n not-found]))
103
+
104
+ (defprotocol ISeq
105
+ (-first [coll])
106
+ (-rest [coll]))
107
+
108
+ (defprotocol ILookup
109
+ (-lookup [o k] [o k not-found]))
110
+
111
+ (defprotocol IAssociative
112
+ (-contains-key? [coll k])
113
+ #_(-entry-at [coll k])
114
+ (-assoc [coll k v]))
115
+
116
+ (defprotocol IMap
117
+ #_(-assoc-ex [coll k v])
118
+ (-dissoc [coll k]))
119
+
120
+ (defprotocol ISet
121
+ (-disjoin [coll v]))
122
+
123
+ (defprotocol IStack
124
+ (-peek [coll])
125
+ (-pop [coll]))
126
+
127
+ (defprotocol IVector
128
+ (-assoc-n [coll n val]))
129
+
130
+ (defprotocol IDeref
131
+ (-deref [o]))
132
+
133
+ (defprotocol IDerefWithTimeout
134
+ (-deref-with-timeout [o msec timeout-val]))
135
+
136
+ (defprotocol IMeta
137
+ (-meta [o]))
138
+
139
+ (defprotocol IWithMeta
140
+ (-with-meta [o meta]))
141
+
142
+ (defprotocol IReduce
143
+ (-reduce [coll f] [coll f start]))
144
+
145
+ (defprotocol IEquiv
146
+ (-equiv [o other]))
147
+
148
+ (defprotocol IHash
149
+ (-hash [o]))
150
+
151
+ (defprotocol ISeqable
152
+ (-seq [o]))
153
+
154
+ (defprotocol ISequential
155
+ "Marker interface indicating a persistent collection of sequential items")
156
+
157
+ (defprotocol IRecord
158
+ "Marker interface indicating a record object")
159
+
160
+ (defprotocol IPrintable
161
+ (-pr-seq [o opts]))
162
+
163
+ (defprotocol IPending
164
+ (-realized? [d]))
165
+
166
+ (defprotocol IWatchable
167
+ (-notify-watches [this oldval newval])
168
+ (-add-watch [this key f])
169
+ (-remove-watch [this key]))
170
+
171
+ ;;;;;;;;;;;;;;;;;;; fundamentals ;;;;;;;;;;;;;;;
172
+ (defn identical? [x y]
173
+ "Tests if 2 arguments are the same object"
174
+ (js* "(~{x} === ~{y})"))
175
+
176
+ (defn = [x y]
177
+ (-equiv x y))
178
+
179
+ (defn nil? [x]
180
+ "Returns true if x is nil, false otherwise."
181
+ (identical? x nil))
182
+
183
+ ;;;;;;;;;;;;;;;;;;; protocols on primitives ;;;;;;;;
184
+ (declare hash-map list equiv-sequential)
185
+
186
+ (extend-type nil
187
+ IEquiv
188
+ (-equiv [_ o] (nil? o))
189
+
190
+ ICounted
191
+ (-count [_] 0)
192
+
193
+ IEmptyableCollection
194
+ (-empty [_] nil)
195
+
196
+ ICollection
197
+ (-conj [_ o] (list o))
198
+
199
+ IPrintable
200
+ (-pr-seq [o] (list "nil"))
201
+
202
+ IIndexed
203
+ (-nth
204
+ ([_ n] nil)
205
+ ([_ n not-found] not-found))
206
+
207
+ ISeq
208
+ (-first [_] nil)
209
+ (-rest [_] (list))
210
+
211
+ ILookup
212
+ (-lookup
213
+ ([o k] nil)
214
+ ([o k not-found] not-found))
215
+
216
+ IAssociative
217
+ (-assoc [_ k v] (hash-map k v))
218
+
219
+ IMap
220
+ (-dissoc [_ k] nil)
221
+
222
+ ISet
223
+ (-disjoin [_ v] nil)
224
+
225
+ IStack
226
+ (-peek [_] nil)
227
+ (-pop [_] nil)
228
+
229
+ IMeta
230
+ (-meta [_] nil)
231
+
232
+ IWithMeta
233
+ (-with-meta [_ meta] nil)
234
+
235
+ IReduce
236
+ (-reduce
237
+ ([_ f] (f))
238
+ ([_ f start] start))
239
+
240
+ IHash
241
+ (-hash [o] 0))
242
+
243
+ (extend-type js/Date
244
+ IEquiv
245
+ (-equiv [o other] (identical? (. o (toString)) (. other (toString)))))
246
+
247
+ (extend-type number
248
+ IEquiv
249
+ (-equiv [x o] (identical? x o))
250
+
251
+ IHash
252
+ (-hash [o] o))
253
+
254
+ (extend-type boolean
255
+ IHash
256
+ (-hash [o] (js* "((~{o} === true) ? 1 : 0)")))
257
+
258
+ (extend-type function
259
+ IHash
260
+ (-hash [o] (goog.getUid o)))
261
+
262
+ ;;this is primitive because & emits call to array-seq
263
+ (defn inc
264
+ "Returns a number one greater than num."
265
+ [x] (js* "(~{x} + 1)"))
266
+
267
+ (defn- ci-reduce
268
+ "Accepts any collection which satisfies the ICount and IIndexed protocols and
269
+ reduces them without incurring seq initialization"
270
+ ([cicoll f]
271
+ (if (= 0 (-count cicoll))
272
+ (f)
273
+ (loop [val (-nth cicoll 0), n 1]
274
+ (if (< n (-count cicoll))
275
+ (recur (f val (-nth cicoll n)) (inc n))
276
+ val))))
277
+ ([cicoll f val]
278
+ (loop [val val, n 0]
279
+ (if (< n (-count cicoll))
280
+ (recur (f val (-nth cicoll n)) (inc n))
281
+ val)))
282
+ ([cicoll f val idx]
283
+ (loop [val val, n idx]
284
+ (if (< n (-count cicoll))
285
+ (recur (f val (-nth cicoll n)) (inc n))
286
+ val))))
287
+
288
+ (deftype IndexedSeq [a i]
289
+ ISeqable
290
+ (-seq [this] this)
291
+ ISeq
292
+ (-first [_] (aget a i))
293
+ (-rest [_] (if (< (inc i) (.length a))
294
+ (IndexedSeq. a (inc i))
295
+ (list)))
296
+
297
+ ICounted
298
+ (-count [_] (- (.length a) i))
299
+
300
+ IIndexed
301
+ (-nth [coll n]
302
+ (let [i (+ n i)]
303
+ (when (< i (.length a))
304
+ (aget a i))))
305
+ (-nth [coll n not-found]
306
+ (let [i (+ n i)]
307
+ (if (< i (.length a))
308
+ (aget a i)
309
+ not-found)))
310
+
311
+ ISequential
312
+ IEquiv
313
+ (-equiv [coll other] (equiv-sequential coll other))
314
+
315
+ ICollection
316
+ (-conj [coll o] (cons o coll))
317
+
318
+ IReduce
319
+ (-reduce [coll f]
320
+ (ci-reduce coll f (aget a i) (inc i)))
321
+ (-reduce [coll f start]
322
+ (ci-reduce coll f start i))
323
+
324
+ IHash
325
+ (-hash [coll] (hash-coll coll)))
326
+
327
+ (defn prim-seq [prim i]
328
+ (when-not (= 0 (.length prim))
329
+ (IndexedSeq. prim i)))
330
+
331
+ (defn array-seq [array i]
332
+ (prim-seq array i))
333
+
334
+ (extend-type array
335
+ ISeqable
336
+ (-seq [array] (array-seq array 0))
337
+
338
+ ICounted
339
+ (-count [a] (.length a))
340
+
341
+ IIndexed
342
+ (-nth
343
+ ([array n]
344
+ (if (< n (.length array)) (aget array n)))
345
+ ([array n not-found]
346
+ (if (< n (.length array)) (aget array n)
347
+ not-found)))
348
+
349
+ ILookup
350
+ (-lookup
351
+ ([array k]
352
+ (aget array k))
353
+ ([array k not-found]
354
+ (-nth array k not-found)))
355
+
356
+ IReduce
357
+ (-reduce
358
+ ([array f]
359
+ (ci-reduce array f))
360
+ ([array f start]
361
+ (ci-reduce array f start))))
362
+
363
+ (defn seq
364
+ "Returns a seq on the collection. If the collection is
365
+ empty, returns nil. (seq nil) returns nil. seq also works on
366
+ Strings."
367
+ [coll]
368
+ (when coll
369
+ (-seq coll)))
370
+
371
+ (defn first
372
+ "Returns the first item in the collection. Calls seq on its
373
+ argument. If coll is nil, returns nil."
374
+ [coll]
375
+ (when-let [s (seq coll)]
376
+ (-first s)))
377
+
378
+ (defn rest
379
+ "Returns a possibly empty seq of the items after the first. Calls seq on its
380
+ argument."
381
+ [coll]
382
+ (-rest (seq coll)))
383
+
384
+ (defn next
385
+ "Returns a seq of the items after the first. Calls seq on its
386
+ argument. If there are no more items, returns nil"
387
+ [coll]
388
+ (when coll
389
+ (seq (rest coll))))
390
+
391
+ (defn second
392
+ "Same as (first (next x))"
393
+ [coll]
394
+ (first (next coll)))
395
+
396
+ (defn ffirst
397
+ "Same as (first (first x))"
398
+ [coll]
399
+ (first (first coll)))
400
+
401
+ (defn nfirst
402
+ "Same as (next (first x))"
403
+ [coll]
404
+ (next (first coll)))
405
+
406
+ (defn fnext
407
+ "Same as (first (next x))"
408
+ [coll]
409
+ (first (next coll)))
410
+
411
+ (defn nnext
412
+ "Same as (next (next x))"
413
+ [coll]
414
+ (next (next coll)))
415
+
416
+ (defn last
417
+ "Return the last item in coll, in linear time"
418
+ [s]
419
+ (if (next s)
420
+ (recur (next s))
421
+ (first s)))
422
+
423
+ (extend-type default
424
+ IEquiv
425
+ (-equiv [x o] (identical? x o))
426
+
427
+ ICounted
428
+ (-count [x]
429
+ (loop [s (seq x) n 0]
430
+ (if s
431
+ (recur (next s) (inc n))
432
+ n))))
433
+
434
+ (defn not
435
+ "Returns true if x is logical false, false otherwise."
436
+ [x] (if x false true))
437
+
438
+ (defn conj
439
+ "conj[oin]. Returns a new collection with the xs
440
+ 'added'. (conj nil item) returns (item). The 'addition' may
441
+ happen at different 'places' depending on the concrete type."
442
+ ([coll x]
443
+ (-conj coll x))
444
+ ([coll x & xs]
445
+ (if xs
446
+ (recur (conj coll x) (first xs) (next xs))
447
+ (conj coll x))))
448
+
449
+ (defn empty
450
+ "Returns an empty collection of the same category as coll, or nil"
451
+ [coll]
452
+ (-empty coll))
453
+
454
+ (defn count
455
+ "Returns the number of items in the collection. (count nil) returns
456
+ 0. Also works on strings, arrays, and Maps"
457
+ [coll]
458
+ (-count coll))
459
+
460
+ (defn nth
461
+ "Returns the value at the index. get returns nil if index out of
462
+ bounds, nth throws an exception unless not-found is supplied. nth
463
+ also works for strings, arrays, regex Matchers and Lists, and,
464
+ in O(n) time, for sequences."
465
+ ([coll n]
466
+ (-nth coll n))
467
+ ([coll n not-found]
468
+ (-nth coll n not-found)))
469
+
470
+ (defn get
471
+ "Returns the value mapped to key, not-found or nil if key not present."
472
+ ([o k]
473
+ (-lookup o k))
474
+ ([o k not-found]
475
+ (-lookup o k not-found)))
476
+
477
+ (defn assoc
478
+ "assoc[iate]. When applied to a map, returns a new map of the
479
+ same (hashed/sorted) type, that contains the mapping of key(s) to
480
+ val(s). When applied to a vector, returns a new vector that
481
+ contains val at index."
482
+ ([coll k v]
483
+ (-assoc coll k v))
484
+ ([coll k v & kvs]
485
+ (let [ret (assoc coll k v)]
486
+ (if kvs
487
+ (recur ret (first kvs) (second kvs) (nnext kvs))
488
+ ret))))
489
+
490
+ (defn dissoc
491
+ "dissoc[iate]. Returns a new map of the same (hashed/sorted) type,
492
+ that does not contain a mapping for key(s)."
493
+ ([coll] coll)
494
+ ([coll k]
495
+ (-dissoc coll k))
496
+ ([coll k & ks]
497
+ (let [ret (dissoc coll k)]
498
+ (if ks
499
+ (recur ret (first ks) (next ks))
500
+ ret))))
501
+
502
+ (defn with-meta
503
+ "Returns an object of the same type and value as obj, with
504
+ map m as its metadata."
505
+ [o meta]
506
+ (-with-meta o meta))
507
+
508
+ (defn meta
509
+ "Returns the metadata of obj, returns nil if there is no metadata."
510
+ [o]
511
+ (when (satisfies? IMeta o)
512
+ (-meta o)))
513
+
514
+ (defn peek
515
+ "For a list or queue, same as first, for a vector, same as, but much
516
+ more efficient than, last. If the collection is empty, returns nil."
517
+ [coll]
518
+ (-peek coll))
519
+
520
+ (defn pop
521
+ "For a list or queue, returns a new list/queue without the first
522
+ item, for a vector, returns a new vector without the last item.
523
+ Note - not the same as next/butlast."
524
+ [coll]
525
+ (-pop coll))
526
+
527
+ (defn disj
528
+ "disj[oin]. Returns a new set of the same (hashed/sorted) type, that
529
+ does not contain key(s)."
530
+ ([coll] coll)
531
+ ([coll k]
532
+ (-disjoin coll k))
533
+ ([coll k & ks]
534
+ (let [ret (disj coll k)]
535
+ (if ks
536
+ (recur ret (first ks) (next ks))
537
+ ret))))
538
+
539
+ (defn hash [o]
540
+ (-hash o))
541
+
542
+ (defn empty?
543
+ "Returns true if coll has no items - same as (not (seq coll)).
544
+ Please use the idiom (seq x) rather than (not (empty? x))"
545
+ [coll] (not (seq coll)))
546
+
547
+ (defn coll?
548
+ "Returns true if x satisfies ICollection"
549
+ [x]
550
+ (if (nil? x)
551
+ false
552
+ (satisfies? ICollection x)))
553
+
554
+ (defn set?
555
+ "Returns true if x satisfies ISet"
556
+ [x]
557
+ (if (nil? x)
558
+ false
559
+ (satisfies? ISet x)))
560
+
561
+ (defn associative?
562
+ "Returns true if coll implements Associative"
563
+ [x] (satisfies? IAssociative x))
564
+
565
+ (defn sequential?
566
+ "Returns true if coll satisfies ISequential"
567
+ [x] (satisfies? ISequential x))
568
+
569
+ (defn counted?
570
+ "Returns true if coll implements count in constant time"
571
+ [x] (satisfies? ICounted x))
572
+
573
+ (defn map?
574
+ "Return true if x satisfies IMap"
575
+ [x]
576
+ (if (nil? x)
577
+ false
578
+ (satisfies? IMap x)))
579
+
580
+ (defn vector?
581
+ "Return true if x satisfies IVector"
582
+ [x] (satisfies? IVector x))
583
+
584
+ ;;;;;;;;;;;;;;;;;;;; js primitives ;;;;;;;;;;;;
585
+ (defn js-obj []
586
+ (js* "{}"))
587
+
588
+ (defn js-keys [obj]
589
+ (let [keys (array)]
590
+ (goog.object/forEach obj (fn [val key obj] (.push keys key)))
591
+ keys))
592
+
593
+ (defn js-delete [obj key]
594
+ (js* "delete ~{obj}[~{key}]"))
595
+
596
+ ;;;;;;;;;;;;;;;; preds ;;;;;;;;;;;;;;;;;;
597
+
598
+ (def ^:private lookup-sentinel (js-obj))
599
+
600
+ (defn false?
601
+ "Returns true if x is the value false, false otherwise."
602
+ [x] (js* "~{x} === false"))
603
+
604
+ (defn true?
605
+ "Returns true if x is the value true, false otherwise."
606
+ [x] (js* "~{x} === true"))
607
+
608
+ (defn undefined? [x]
609
+ (js* "(void 0 === ~{x})"))
610
+
611
+ (defn instance? [t o]
612
+ (js* "(~{o} instanceof ~{t})"))
613
+
614
+ (defn seq?
615
+ "Return true if s satisfies ISeq"
616
+ [s]
617
+ (if (nil? s)
618
+ false
619
+ (satisfies? ISeq s)))
620
+
621
+ (defn boolean [x]
622
+ (if x true false))
623
+
624
+ (defn string? [x]
625
+ (and (goog/isString x)
626
+ (not (or (= (.charAt x 0) \uFDD0)
627
+ (= (.charAt x 0) \uFDD1)))))
628
+
629
+ (defn keyword? [x]
630
+ (and (goog/isString x)
631
+ (= (.charAt x 0) \uFDD0)))
632
+
633
+ (defn symbol? [x]
634
+ (and (goog/isString x)
635
+ (= (.charAt x 0) \uFDD1)))
636
+
637
+ (defn number? [n]
638
+ (goog/isNumber n))
639
+
640
+ (defn fn? [f]
641
+ (goog/isFunction f))
642
+
643
+ (defn integer?
644
+ "Returns true if n is an integer. Warning: returns true on underflow condition."
645
+ [n]
646
+ (and (number? n)
647
+ (js* "(~{n} == ~{n}.toFixed())")))
648
+
649
+ (defn contains?
650
+ "Returns true if key is present in the given collection, otherwise
651
+ returns false. Note that for numerically indexed collections like
652
+ vectors and arrays, this tests if the numeric key is within the
653
+ range of indexes. 'contains?' operates constant or logarithmic time;
654
+ it will not perform a linear search for a value. See also 'some'."
655
+ [coll v]
656
+ (if (identical? (-lookup coll v lookup-sentinel) lookup-sentinel)
657
+ false
658
+ true))
659
+
660
+ (defn find
661
+ "Returns the map entry for key, or nil if key not present."
662
+ [coll k]
663
+ (when (and coll
664
+ (associative? coll)
665
+ (contains? coll k))
666
+ [k (-lookup coll k)]))
667
+
668
+ (defn distinct?
669
+ "Returns true if no two of the arguments are ="
670
+ ([x] true)
671
+ ([x y] (not (= x y)))
672
+ ([x y & more]
673
+ (if (not (= x y))
674
+ (loop [s #{x y} xs more]
675
+ (let [x (first xs)
676
+ etc (next xs)]
677
+ (if xs
678
+ (if (contains? s x)
679
+ false
680
+ (recur (conj s x) etc))
681
+ true)))
682
+ false)))
683
+
684
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Seq fns ;;;;;;;;;;;;;;;;
685
+
686
+ (defn compare
687
+ "Comparator. Returns a negative number, zero, or a positive number
688
+ when x is logically 'less than', 'equal to', or 'greater than'
689
+ y. Uses google.array.defaultCompare."
690
+ [x y] (garray/defaultCompare x y))
691
+
692
+ (defn ^:private fn->comparator
693
+ "Given a fn that might be boolean valued or a comparator,
694
+ return a fn that is a comparator."
695
+ [f]
696
+ (if (= f compare)
697
+ compare
698
+ (fn [x y]
699
+ (let [r (f x y)]
700
+ (if (number? r)
701
+ r
702
+ (if r
703
+ -1
704
+ (if (f y x) 1 0)))))))
705
+
706
+ (declare to-array)
707
+ (defn sort
708
+ "Returns a sorted sequence of the items in coll. Comp can be
709
+ boolean-valued comparison funcion, or a -/0/+ valued comparator.
710
+ Comp defaults to compare."
711
+ ([coll]
712
+ (sort compare coll))
713
+ ([comp coll]
714
+ (if (seq coll)
715
+ (let [a (to-array coll)]
716
+ ;; matching Clojure's stable sort, though docs don't promise it
717
+ (garray/stableSort a (fn->comparator comp))
718
+ (seq a))
719
+ ())))
720
+
721
+ (defn sort-by
722
+ "Returns a sorted sequence of the items in coll, where the sort
723
+ order is determined by comparing (keyfn item). Comp can be
724
+ boolean-valued comparison funcion, or a -/0/+ valued comparator.
725
+ Comp defaults to compare."
726
+ ([keyfn coll]
727
+ (sort-by keyfn compare coll))
728
+ ([keyfn comp coll]
729
+ (sort (fn [x y] ((fn->comparator comp) (keyfn x) (keyfn y))) coll)))
730
+
731
+ (defn reduce
732
+ "f should be a function of 2 arguments. If val is not supplied,
733
+ returns the result of applying f to the first 2 items in coll, then
734
+ applying f to that result and the 3rd item, etc. If coll contains no
735
+ items, f must accept no arguments as well, and reduce returns the
736
+ result of calling f with no arguments. If coll has only 1 item, it
737
+ is returned and f is not called. If val is supplied, returns the
738
+ result of applying f to val and the first item in coll, then
739
+ applying f to that result and the 2nd item, etc. If coll contains no
740
+ items, returns val and f is not called."
741
+ ([f coll]
742
+ (-reduce coll f))
743
+ ([f val coll]
744
+ (-reduce coll f val)))
745
+
746
+ ; simple reduce based on seqs, used as default
747
+ (defn- seq-reduce
748
+ ([f coll]
749
+ (if-let [s (seq coll)]
750
+ (reduce f (first s) (next s))
751
+ (f)))
752
+ ([f val coll]
753
+ (loop [val val, coll (seq coll)]
754
+ (if coll
755
+ (recur (f val (first coll)) (next coll))
756
+ val))))
757
+
758
+ (extend-type default
759
+ IReduce
760
+ (-reduce
761
+ ([coll f]
762
+ (seq-reduce f coll))
763
+ ([coll f start]
764
+ (seq-reduce f start coll))))
765
+
766
+ ;;; Math - variadic forms will not work until the following implemented:
767
+ ;;; first, next, reduce
768
+
769
+ (defn +
770
+ "Returns the sum of nums. (+) returns 0."
771
+ ([] 0)
772
+ ([x] x)
773
+ ([x y] (js* "(~{x} + ~{y})"))
774
+ ([x y & more] (reduce + (+ x y) more)))
775
+
776
+ (defn -
777
+ "If no ys are supplied, returns the negation of x, else subtracts
778
+ the ys from x and returns the result."
779
+ ([x] (js* "(- ~{x})"))
780
+ ([x y] (js* "(~{x} - ~{y})"))
781
+ ([x y & more] (reduce - (- x y) more)))
782
+
783
+ (defn *
784
+ "Returns the product of nums. (*) returns 1."
785
+ ([] 1)
786
+ ([x] x)
787
+ ([x y] (js* "(~{x} * ~{y})"))
788
+ ([x y & more] (reduce * (* x y) more)))
789
+
790
+ (defn /
791
+ "If no denominators are supplied, returns 1/numerator,
792
+ else returns numerator divided by all of the denominators."
793
+ ([x] (js* "(1 / ~{x})"))
794
+ ([x y] (js* "(~{x} / ~{y})"))
795
+ ([x y & more] (reduce / (/ x y) more)))
796
+
797
+ (defn <
798
+ "Returns non-nil if nums are in monotonically increasing order,
799
+ otherwise false."
800
+ ([x] true)
801
+ ([x y] (js* "(~{x} < ~{y})"))
802
+ ([x y & more]
803
+ (if (< x y)
804
+ (if (next more)
805
+ (recur y (first more) (next more))
806
+ (< y (first more)))
807
+ false)))
808
+
809
+ (defn <=
810
+ "Returns non-nil if nums are in monotonically non-decreasing order,
811
+ otherwise false."
812
+ ([x] true)
813
+ ([x y] (js* "(~{x} <= ~{y})"))
814
+ ([x y & more]
815
+ (if (<= x y)
816
+ (if (next more)
817
+ (recur y (first more) (next more))
818
+ (<= y (first more)))
819
+ false)))
820
+
821
+ (defn >
822
+ "Returns non-nil if nums are in monotonically decreasing order,
823
+ otherwise false."
824
+ ([x] true)
825
+ ([x y] (js* "(~{x} > ~{y})"))
826
+ ([x y & more]
827
+ (if (> x y)
828
+ (if (next more)
829
+ (recur y (first more) (next more))
830
+ (> y (first more)))
831
+ false)))
832
+
833
+ (defn >=
834
+ "Returns non-nil if nums are in monotonically non-increasing order,
835
+ otherwise false."
836
+ ([x] true)
837
+ ([x y] (js* "(~{x} >= ~{y})"))
838
+ ([x y & more]
839
+ (if (>= x y)
840
+ (if (next more)
841
+ (recur y (first more) (next more))
842
+ (>= y (first more)))
843
+ false)))
844
+
845
+ (defn dec
846
+ "Returns a number one less than num."
847
+ [x] (- x 1))
848
+
849
+ (defn max
850
+ "Returns the greatest of the nums."
851
+ ([x] x)
852
+ ([x y] (js* "((~{x} > ~{y}) ? x : y)"))
853
+ ([x y & more]
854
+ (reduce max (max x y) more)))
855
+
856
+ (defn min
857
+ "Returns the least of the nums."
858
+ ([x] x)
859
+ ([x y] (js* "((~{x} < ~{y}) ? x : y)"))
860
+ ([x y & more]
861
+ (reduce min (min x y) more)))
862
+
863
+ (defn- fix [q]
864
+ (if (>= q 0)
865
+ (Math/floor q)
866
+ (Math/ceil q)))
867
+
868
+ (defn mod
869
+ "Modulus of num and div. Truncates toward negative infinity."
870
+ [n d]
871
+ (js* "(~{n} % ~{d})"))
872
+
873
+ (defn quot
874
+ "quot[ient] of dividing numerator by denominator."
875
+ [n d]
876
+ (let [rem (mod n d)]
877
+ (fix (js* "((~{n} - ~{rem}) / ~{d})"))))
878
+
879
+ (defn rem
880
+ "remainder of dividing numerator by denominator."
881
+ [n d]
882
+ (let [q (quot n d)]
883
+ (js* "(~{n} - (~{d} * ~{q}))")))
884
+
885
+ (defn rand
886
+ "Returns a random floating point number between 0 (inclusive) and n (default 1) (exclusive)."
887
+ ([] (Math/random))
888
+ ([n] (* n (rand))))
889
+
890
+ (defn rand-int
891
+ "Returns a random integer between 0 (inclusive) and n (exclusive)."
892
+ [n] (fix (rand n)))
893
+
894
+ (defn bit-xor
895
+ "Bitwise exclusive or"
896
+ [x y] (js* "(~{x} ^ ~{y})"))
897
+
898
+ (defn bit-and
899
+ "Bitwise and"
900
+ [x y] (js* "(~{x} & ~{y})"))
901
+
902
+ (defn bit-or
903
+ "Bitwise or"
904
+ [x y] (js* "(~{x} | ~{y})"))
905
+
906
+ (defn bit-and-not
907
+ "Bitwise and"
908
+ [x y] (js* "(~{x} & ~~{y})"))
909
+
910
+ (defn bit-clear
911
+ "Clear bit at index n"
912
+ [x n]
913
+ (js* "(~{x} & ~(1 << ~{n}))"))
914
+
915
+ (defn bit-flip
916
+ "Flip bit at index n"
917
+ [x n]
918
+ (js* "(~{x} ^ (1 << ~{n}))"))
919
+
920
+ (defn bit-not
921
+ "Bitwise complement"
922
+ [x] (js* "(~~{x})"))
923
+
924
+ (defn bit-set
925
+ "Set bit at index n"
926
+ [x n]
927
+ (js* "(~{x} | (1 << ~{n}))"))
928
+
929
+ (defn bit-test
930
+ "Test bit at index n"
931
+ [x n]
932
+ (js* "((~{x} & (1 << ~{n})) != 0)"))
933
+
934
+
935
+ (defn bit-shift-left
936
+ "Bitwise shift left"
937
+ [x n] (js* "(~{x} << ~{n})"))
938
+
939
+ (defn bit-shift-right
940
+ "Bitwise shift right"
941
+ [x n] (js* "(~{x} >> ~{n})"))
942
+
943
+ (defn ==
944
+ "Returns non-nil if nums all have the equivalent
945
+ value (type-independent), otherwise false"
946
+ ([x] true)
947
+ ([x y] (-equiv x y))
948
+ ([x y & more]
949
+ (if (== x y)
950
+ (if (next more)
951
+ (recur y (first more) (next more))
952
+ (== y (first more)))
953
+ false)))
954
+
955
+ (defn pos?
956
+ "Returns true if num is greater than zero, else false"
957
+ [n] (< 0 n))
958
+
959
+ (defn zero? [n]
960
+ (== 0 n))
961
+
962
+ (defn neg?
963
+ "Returns true if num is less than zero, else false"
964
+ [x] (js* "(~{x} < 0)"))
965
+
966
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; protocols for host types ;;;;;;
967
+
968
+
969
+
970
+ (defn nthnext
971
+ "Returns the nth next of coll, (seq coll) when n is 0."
972
+ [coll n]
973
+ (loop [n n xs (seq coll)]
974
+ (if (and xs (pos? n))
975
+ (recur (dec n) (next xs))
976
+ xs)))
977
+
978
+ (extend-type default
979
+ IIndexed
980
+ (-nth
981
+ ([coll n]
982
+ (if-let [xs (nthnext coll n)]
983
+ (first xs)
984
+ (throw (js/Error. "Index out of bounds"))))
985
+ ([coll n not-found]
986
+ (if-let [xs (nthnext coll n)]
987
+ (first xs)
988
+ not-found))))
989
+
990
+
991
+ ;;;;;;;;;;;;;;;;;;;;;;;;;; basics ;;;;;;;;;;;;;;;;;;
992
+
993
+ (defn- str*
994
+ "Internal - do not use!"
995
+ ([] "")
996
+ ([x] (cond
997
+ (nil? x) ""
998
+ :else (. x (toString))))
999
+ ([x & ys]
1000
+ ((fn [sb more]
1001
+ (if more
1002
+ (recur (. sb (append (str* (first more)))) (next more))
1003
+ (str* sb)))
1004
+ (gstring/StringBuffer. (str* x)) ys)))
1005
+
1006
+ (defn str
1007
+ "With no args, returns the empty string. With one arg x, returns
1008
+ x.toString(). (str nil) returns the empty string. With more than
1009
+ one arg, returns the concatenation of the str values of the args."
1010
+ ([] "")
1011
+ ([x] (cond
1012
+ (symbol? x) (. x (substring 2 (.length x)))
1013
+ (keyword? x) (str* ":" (. x (substring 2 (.length x))))
1014
+ (nil? x) ""
1015
+ :else (. x (toString))))
1016
+ ([x & ys]
1017
+ (apply str* x ys)))
1018
+
1019
+ (defn subs
1020
+ "Returns the substring of s beginning at start inclusive, and ending
1021
+ at end (defaults to length of string), exclusive."
1022
+ ([s start] (.substring s start))
1023
+ ([s start end] (.substring s start end)))
1024
+
1025
+ (defn symbol
1026
+ "Returns a Symbol with the given namespace and name."
1027
+ ([name] (cond (symbol? name) name
1028
+ (keyword? name) (str* "\uFDD1" "'" (subs name 2)))
1029
+ :else (str* "\uFDD1" "'" name))
1030
+ ([ns name] (symbol (str* ns "/" name))))
1031
+
1032
+ (defn keyword
1033
+ "Returns a Keyword with the given namespace and name. Do not use :
1034
+ in the keyword strings, it will be added automatically."
1035
+ ([name] (cond (keyword? name) name
1036
+ (symbol? name) (str* "\uFDD0" "'" (subs name 2))
1037
+ :else (str* "\uFDD0" "'" name)))
1038
+ ([ns name] (keyword (str* ns "/" name))))
1039
+
1040
+
1041
+
1042
+ (defn- equiv-sequential
1043
+ "Assumes x is sequential. Returns true if x equals y, otherwise
1044
+ returns false."
1045
+ [x y]
1046
+ (boolean
1047
+ (when (sequential? y)
1048
+ (loop [xs (seq x) ys (seq y)]
1049
+ (cond (nil? xs) (nil? ys)
1050
+ (nil? ys) false
1051
+ (= (first xs) (first ys)) (recur (next xs) (next ys))
1052
+ :else false)))))
1053
+
1054
+ (defn hash-combine [seed hash]
1055
+ ; a la boost
1056
+ (bit-xor seed (+ hash 0x9e3779b9
1057
+ (bit-shift-left seed 6)
1058
+ (bit-shift-right seed 2))))
1059
+
1060
+ (defn- hash-coll [coll]
1061
+ (reduce #(hash-combine %1 (hash %2)) (hash (first coll)) (next coll)))
1062
+
1063
+ (defn- extend-object!
1064
+ "Takes a JavaScript object and a map of names to functions and
1065
+ attaches said functions as methods on the object. Any references to
1066
+ JavaScript's implict this (via the this-as macro) will resolve to the
1067
+ object that the function is attached."
1068
+ [obj fn-map]
1069
+ (doseq [[key-name f] fn-map]
1070
+ (let [str-name (name key-name)]
1071
+ (js* "~{obj}[~{str-name}] = ~{f}")))
1072
+ obj)
1073
+
1074
+ ;;;;;;;;;;;;;;;; cons ;;;;;;;;;;;;;;;;
1075
+ (deftype List [meta first rest count]
1076
+ IWithMeta
1077
+ (-with-meta [coll meta] (List. meta first rest count))
1078
+
1079
+ IMeta
1080
+ (-meta [coll] meta)
1081
+
1082
+ ISeq
1083
+ (-first [coll] first)
1084
+ (-rest [coll] rest)
1085
+
1086
+ IStack
1087
+ (-peek [coll] first)
1088
+ (-pop [coll] (-rest coll))
1089
+
1090
+ ICollection
1091
+ (-conj [coll o] (List. meta o coll (inc count)))
1092
+
1093
+ IEmptyableCollection
1094
+ (-empty [coll] cljs.core.List/EMPTY)
1095
+
1096
+ ISequential
1097
+ IEquiv
1098
+ (-equiv [coll other] (equiv-sequential coll other))
1099
+
1100
+ IHash
1101
+ (-hash [coll] (hash-coll coll))
1102
+
1103
+ ISeqable
1104
+ (-seq [coll] coll)
1105
+
1106
+ ICounted
1107
+ (-count [coll] count))
1108
+
1109
+ (deftype EmptyList [meta]
1110
+ IWithMeta
1111
+ (-with-meta [coll meta] (EmptyList. meta))
1112
+
1113
+ IMeta
1114
+ (-meta [coll] meta)
1115
+
1116
+ ISeq
1117
+ (-first [coll] nil)
1118
+ (-rest [coll] nil)
1119
+
1120
+ IStack
1121
+ (-peek [coll] nil)
1122
+ (-pop [coll] #_(throw (js/Error. "Can't pop empty list")))
1123
+
1124
+ ICollection
1125
+ (-conj [coll o] (List. meta o nil 1))
1126
+
1127
+ IEmptyableCollection
1128
+ (-empty [coll] coll)
1129
+
1130
+ ISequential
1131
+ IEquiv
1132
+ (-equiv [coll other] (equiv-sequential coll other))
1133
+
1134
+ IHash
1135
+ (-hash [coll] (hash-coll coll))
1136
+
1137
+ ISeqable
1138
+ (-seq [coll] nil)
1139
+
1140
+ ICounted
1141
+ (-count [coll] 0))
1142
+
1143
+ (set! cljs.core.List/EMPTY (EmptyList. nil))
1144
+
1145
+ (defn reverse
1146
+ "Returns a seq of the items in coll in reverse order. Not lazy."
1147
+ [coll]
1148
+ (reduce conj () coll))
1149
+
1150
+ (defn list [& items]
1151
+ (reduce conj () (reverse items)))
1152
+
1153
+ (deftype Cons [meta first rest]
1154
+ IWithMeta
1155
+ (-with-meta [coll meta] (Cons. meta first rest))
1156
+
1157
+ IMeta
1158
+ (-meta [coll] meta)
1159
+
1160
+ ISeq
1161
+ (-first [coll] first)
1162
+ (-rest [coll] (if (nil? rest) () rest))
1163
+
1164
+ ICollection
1165
+ (-conj [coll o] (Cons. nil o coll))
1166
+
1167
+ IEmptyableCollection
1168
+ (-empty [coll] (with-meta cljs.core.List/EMPTY meta))
1169
+
1170
+ ISequential
1171
+ IEquiv
1172
+ (-equiv [coll other] (equiv-sequential coll other))
1173
+
1174
+ IHash
1175
+ (-hash [coll] (hash-coll coll))
1176
+
1177
+ ISeqable
1178
+ (-seq [coll] coll))
1179
+
1180
+ (defn cons
1181
+ "Returns a new seq where x is the first element and seq is the rest."
1182
+ [x seq]
1183
+ (Cons. nil x seq))
1184
+
1185
+ (declare hash-map)
1186
+
1187
+ (extend-type string
1188
+ IHash
1189
+ (-hash [o] (goog.string/hashCode o))
1190
+
1191
+ ISeqable
1192
+ (-seq [string] (prim-seq string 0))
1193
+
1194
+ ICounted
1195
+ (-count [s] (.length s))
1196
+
1197
+ IIndexed
1198
+ (-nth
1199
+ ([string n]
1200
+ (if (< n (-count string)) (.charAt string n)))
1201
+ ([string n not-found]
1202
+ (if (< n (-count string)) (.charAt string n)
1203
+ not-found)))
1204
+
1205
+ ILookup
1206
+ (-lookup
1207
+ ([string k]
1208
+ (-nth string k))
1209
+ ([string k not_found]
1210
+ (-nth string k not_found)))
1211
+
1212
+ IReduce
1213
+ (-reduce
1214
+ ([string f]
1215
+ (ci-reduce string f))
1216
+ ([string f start]
1217
+ (ci-reduce string f start))))
1218
+
1219
+ ;;hrm
1220
+ (set! js/String.prototype.call
1221
+ (fn
1222
+ ([_ coll]
1223
+ (get coll (js* "this.toString()")))
1224
+ ([_ coll not-found]
1225
+ (get coll (js* "this.toString()") not-found))))
1226
+
1227
+ (set! js/String.prototype.apply
1228
+ (fn
1229
+ [s args]
1230
+ (if (< (count args) 2)
1231
+ (get (aget args 0) s)
1232
+ (get (aget args 0) s (aget args 1)))))
1233
+
1234
+ ; could use reify
1235
+ ;;; LazySeq ;;;
1236
+
1237
+ (defn- lazy-seq-value [lazy-seq]
1238
+ (let [x (.x lazy-seq)]
1239
+ (if (.realized lazy-seq)
1240
+ x
1241
+ (do
1242
+ (set! (.x lazy-seq) (x))
1243
+ (set! (.realized lazy-seq) true)
1244
+ (.x lazy-seq)))))
1245
+
1246
+ (deftype LazySeq [meta realized x]
1247
+ IWithMeta
1248
+ (-with-meta [coll meta] (LazySeq. meta realized x))
1249
+
1250
+ IMeta
1251
+ (-meta [coll] meta)
1252
+
1253
+ ISeq
1254
+ (-first [coll] (first (lazy-seq-value coll)))
1255
+ (-rest [coll] (rest (lazy-seq-value coll)))
1256
+
1257
+ ICollection
1258
+ (-conj [coll o] (cons o coll))
1259
+
1260
+ IEmptyableCollection
1261
+ (-empty [coll] (with-meta cljs.core.List/EMPTY meta))
1262
+
1263
+ ISequential
1264
+ IEquiv
1265
+ (-equiv [coll other] (equiv-sequential coll other))
1266
+
1267
+ IHash
1268
+ (-hash [coll] (hash-coll coll))
1269
+
1270
+ ISeqable
1271
+ (-seq [coll] (seq (lazy-seq-value coll))))
1272
+
1273
+ ;;;;;;;;;;;;;;;;
1274
+
1275
+ (defn to-array
1276
+ "Naive impl of to-array as a start."
1277
+ [s]
1278
+ (let [ary (array)]
1279
+ (loop [s s]
1280
+ (if (seq s)
1281
+ (do (. ary push (first s))
1282
+ (recur (next s)))
1283
+ ary))))
1284
+
1285
+ (defn- bounded-count [s n]
1286
+ (loop [s s i n sum 0]
1287
+ (if (and (pos? i)
1288
+ (seq s))
1289
+ (recur (next s)
1290
+ (dec i)
1291
+ (inc sum))
1292
+ sum)))
1293
+
1294
+ (defn spread
1295
+ [arglist]
1296
+ (cond
1297
+ (nil? arglist) nil
1298
+ (nil? (next arglist)) (seq (first arglist))
1299
+ :else (cons (first arglist)
1300
+ (spread (next arglist)))))
1301
+
1302
+ (defn concat
1303
+ "Returns a lazy seq representing the concatenation of the elements in the supplied colls."
1304
+ ([] (lazy-seq nil))
1305
+ ([x] (lazy-seq x))
1306
+ ([x y]
1307
+ (lazy-seq
1308
+ (let [s (seq x)]
1309
+ (if s
1310
+ (cons (first s) (concat (rest s) y))
1311
+ y))))
1312
+ ([x y & zs]
1313
+ (let [cat (fn cat [xys zs]
1314
+ (lazy-seq
1315
+ (let [xys (seq xys)]
1316
+ (if xys
1317
+ (cons (first xys) (cat (rest xys) zs))
1318
+ (when zs
1319
+ (cat (first zs) (next zs)))))))]
1320
+ (cat (concat x y) zs))))
1321
+
1322
+ (defn list*
1323
+ "Creates a new list containing the items prepended to the rest, the
1324
+ last of which will be treated as a sequence."
1325
+ ([args] (seq args))
1326
+ ([a args] (cons a args))
1327
+ ([a b args] (cons a (cons b args)))
1328
+ ([a b c args] (cons a (cons b (cons c args))))
1329
+ ([a b c d & more]
1330
+ (cons a (cons b (cons c (cons d (spread more)))))))
1331
+
1332
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; apply ;;;;;;;;;;;;;;;;
1333
+
1334
+ (defn apply
1335
+ "Applies fn f to the argument list formed by prepending intervening arguments to args.
1336
+ First cut. Not lazy. Needs to use emitted toApply."
1337
+ ([f args]
1338
+ (let [fixed-arity (. f cljs$lang$maxFixedArity)]
1339
+ (if (. f cljs$lang$applyTo)
1340
+ (if (<= (bounded-count args (inc fixed-arity))
1341
+ fixed-arity)
1342
+ (. f apply f (to-array args))
1343
+ (. f cljs$lang$applyTo args))
1344
+ (. f apply f (to-array args)))))
1345
+ ([f x args]
1346
+ (let [arglist (list* x args)
1347
+ fixed-arity (. f cljs$lang$maxFixedArity)]
1348
+ (if (. f cljs$lang$applyTo)
1349
+ (if (<= (bounded-count arglist fixed-arity)
1350
+ fixed-arity)
1351
+ (. f apply f (to-array arglist))
1352
+ (. f cljs$lang$applyTo arglist))
1353
+ (. f apply f (to-array arglist)))))
1354
+ ([f x y args]
1355
+ (let [arglist (list* x y args)
1356
+ fixed-arity (. f cljs$lang$maxFixedArity)]
1357
+ (if (. f cljs$lang$applyTo)
1358
+ (if (<= (bounded-count arglist fixed-arity)
1359
+ fixed-arity)
1360
+ (. f apply f (to-array arglist))
1361
+ (. f cljs$lang$applyTo arglist))
1362
+ (. f apply f (to-array arglist)))))
1363
+ ([f x y z args]
1364
+ (let [arglist (list* x y z args)
1365
+ fixed-arity (. f cljs$lang$maxFixedArity)]
1366
+ (if (. f cljs$lang$applyTo)
1367
+ (if (<= (bounded-count arglist fixed-arity)
1368
+ fixed-arity)
1369
+ (. f apply f (to-array arglist))
1370
+ (. f cljs$lang$applyTo arglist))
1371
+ (. f apply f (to-array arglist)))))
1372
+ ([f a b c d & args]
1373
+ (let [arglist (cons a (cons b (cons c (cons d (spread args)))))
1374
+ fixed-arity (. f cljs$lang$maxFixedArity)]
1375
+ (if (. f cljs$lang$applyTo)
1376
+ (if (<= (bounded-count arglist fixed-arity)
1377
+ fixed-arity)
1378
+ (. f apply f (to-array arglist))
1379
+ (. f cljs$lang$applyTo arglist))
1380
+ (. f apply f (to-array arglist))))))
1381
+
1382
+ (defn vary-meta
1383
+ "Returns an object of the same type and value as obj, with
1384
+ (apply f (meta obj) args) as its metadata."
1385
+ [obj f & args]
1386
+ (with-meta obj (apply f (meta obj) args)))
1387
+
1388
+ (defn not=
1389
+ "Same as (not (= obj1 obj2))"
1390
+ ([x] false)
1391
+ ([x y] (not (= x y)))
1392
+ ([x y & more]
1393
+ (not (apply = x y more))))
1394
+
1395
+ (defn not-empty
1396
+ "If coll is empty, returns nil, else coll"
1397
+ [coll] (when (seq coll) coll))
1398
+
1399
+ (defn every?
1400
+ "Returns true if (pred x) is logical true for every x in coll, else
1401
+ false."
1402
+ [pred coll]
1403
+ (cond
1404
+ (nil? (seq coll)) true
1405
+ (pred (first coll)) (recur pred (next coll))
1406
+ :else false))
1407
+
1408
+ (defn not-every?
1409
+ "Returns false if (pred x) is logical true for every x in
1410
+ coll, else true."
1411
+ [pred coll] (not (every? pred coll)))
1412
+
1413
+ (defn some
1414
+ "Returns the first logical true value of (pred x) for any x in coll,
1415
+ else nil. One common idiom is to use a set as pred, for example
1416
+ this will return :fred if :fred is in the sequence, otherwise nil:
1417
+ (some #{:fred} coll)"
1418
+ [pred coll]
1419
+ (when (seq coll)
1420
+ (or (pred (first coll)) (recur pred (next coll)))))
1421
+
1422
+ (defn not-any?
1423
+ "Returns false if (pred x) is logical true for any x in coll,
1424
+ else true."
1425
+ [pred coll] (not (some pred coll)))
1426
+
1427
+ (defn even?
1428
+ "Returns true if n is even, throws an exception if n is not an integer"
1429
+ [n] (if (integer? n)
1430
+ (zero? (bit-and n 1))
1431
+ (throw (js/Error. (str "Argument must be an integer: " n)))))
1432
+
1433
+ (defn odd?
1434
+ "Returns true if n is odd, throws an exception if n is not an integer"
1435
+ [n] (not (even? n)))
1436
+
1437
+ (defn identity [x] x)
1438
+
1439
+ (defn complement
1440
+ "Takes a fn f and returns a fn that takes the same arguments as f,
1441
+ has the same effects, if any, and returns the opposite truth value."
1442
+ [f]
1443
+ (fn
1444
+ ([] (not (f)))
1445
+ ([x] (not (f x)))
1446
+ ([x y] (not (f x y)))
1447
+ ([x y & zs] (not (apply f x y zs)))))
1448
+
1449
+ (defn constantly
1450
+ "Returns a function that takes any number of arguments and returns x."
1451
+ [x] (fn [& args] x))
1452
+
1453
+ (defn comp
1454
+ "Takes a set of functions and returns a fn that is the composition
1455
+ of those fns. The returned fn takes a variable number of args,
1456
+ applies the rightmost of fns to the args, the next
1457
+ fn (right-to-left) to the result, etc.
1458
+
1459
+ TODO: Implement apply"
1460
+ ([] identity)
1461
+ ([f] f)
1462
+ ([f g]
1463
+ (fn
1464
+ ([] (f (g)))
1465
+ ([x] (f (g x)))
1466
+ ([x y] (f (g x y)))
1467
+ ([x y z] (f (g x y z)))
1468
+ ([x y z & args] (f (apply g x y z args)))))
1469
+ ([f g h]
1470
+ (fn
1471
+ ([] (f (g (h))))
1472
+ ([x] (f (g (h x))))
1473
+ ([x y] (f (g (h x y))))
1474
+ ([x y z] (f (g (h x y z))))
1475
+ ([x y z & args] (f (g (apply h x y z args))))))
1476
+ ([f1 f2 f3 & fs]
1477
+ (let [fs (reverse (list* f1 f2 f3 fs))]
1478
+ (fn [& args]
1479
+ (loop [ret (apply (first fs) args) fs (next fs)]
1480
+ (if fs
1481
+ (recur ((first fs) ret) (next fs))
1482
+ ret))))))
1483
+
1484
+ (defn partial
1485
+ "Takes a function f and fewer than the normal arguments to f, and
1486
+ returns a fn that takes a variable number of additional args. When
1487
+ called, the returned function calls f with args + additional args.
1488
+
1489
+ TODO: Implement apply"
1490
+ ([f arg1]
1491
+ (fn [& args] (apply f arg1 args)))
1492
+ ([f arg1 arg2]
1493
+ (fn [& args] (apply f arg1 arg2 args)))
1494
+ ([f arg1 arg2 arg3]
1495
+ (fn [& args] (apply f arg1 arg2 arg3 args)))
1496
+ ([f arg1 arg2 arg3 & more]
1497
+ (fn [& args] (apply f arg1 arg2 arg3 (concat more args)))))
1498
+
1499
+ (defn fnil
1500
+ "Takes a function f, and returns a function that calls f, replacing
1501
+ a nil first argument to f with the supplied value x. Higher arity
1502
+ versions can replace arguments in the second and third
1503
+ positions (y, z). Note that the function f can take any number of
1504
+ arguments, not just the one(s) being nil-patched."
1505
+ ([f x]
1506
+ (fn
1507
+ ([a] (f (if (nil? a) x a)))
1508
+ ([a b] (f (if (nil? a) x a) b))
1509
+ ([a b c] (f (if (nil? a) x a) b c))
1510
+ ([a b c & ds] (apply f (if (nil? a) x a) b c ds))))
1511
+ ([f x y]
1512
+ (fn
1513
+ ([a b] (f (if (nil? a) x a) (if (nil? b) y b)))
1514
+ ([a b c] (f (if (nil? a) x a) (if (nil? b) y b) c))
1515
+ ([a b c & ds] (apply f (if (nil? a) x a) (if (nil? b) y b) c ds))))
1516
+ ([f x y z]
1517
+ (fn
1518
+ ([a b] (f (if (nil? a) x a) (if (nil? b) y b)))
1519
+ ([a b c] (f (if (nil? a) x a) (if (nil? b) y b) (if (nil? c) z c)))
1520
+ ([a b c & ds] (apply f (if (nil? a) x a) (if (nil? b) y b) (if (nil? c) z c) ds)))))
1521
+
1522
+ (defn map-indexed
1523
+ "Returns a lazy sequence consisting of the result of applying f to 0
1524
+ and the first item of coll, followed by applying f to 1 and the second
1525
+ item in coll, etc, until coll is exhausted. Thus function f should
1526
+ accept 2 arguments, index and item."
1527
+ [f coll]
1528
+ (let [mapi (fn mpi [idx coll]
1529
+ (lazy-seq
1530
+ (when-let [s (seq coll)]
1531
+ (cons (f idx (first s))
1532
+ (mpi (inc idx) (rest s))))))]
1533
+ (mapi 0 coll)))
1534
+
1535
+ (defn keep
1536
+ "Returns a lazy sequence of the non-nil results of (f item). Note,
1537
+ this means false return values will be included. f must be free of
1538
+ side-effects."
1539
+ ([f coll]
1540
+ (lazy-seq
1541
+ (when-let [s (seq coll)]
1542
+ (let [x (f (first s))]
1543
+ (if (nil? x)
1544
+ (keep f (rest s))
1545
+ (cons x (keep f (rest s)))))))))
1546
+
1547
+ (defn keep-indexed
1548
+ "Returns a lazy sequence of the non-nil results of (f index item). Note,
1549
+ this means false return values will be included. f must be free of
1550
+ side-effects."
1551
+ ([f coll]
1552
+ (let [keepi (fn kpi [idx coll]
1553
+ (lazy-seq
1554
+ (when-let [s (seq coll)]
1555
+ (let [x (f idx (first s))]
1556
+ (if (nil? x)
1557
+ (kpi (inc idx) (rest s))
1558
+ (cons x (kpi (inc idx) (rest s))))))))]
1559
+ (keepi 0 coll))))
1560
+
1561
+ (defn every-pred
1562
+ "Takes a set of predicates and returns a function f that returns true if all of its
1563
+ composing predicates return a logical true value against all of its arguments, else it returns
1564
+ false. Note that f is short-circuiting in that it will stop execution on the first
1565
+ argument that triggers a logical false result against the original predicates."
1566
+ ([p]
1567
+ (fn ep1
1568
+ ([] true)
1569
+ ([x] (boolean (p x)))
1570
+ ([x y] (boolean (and (p x) (p y))))
1571
+ ([x y z] (boolean (and (p x) (p y) (p z))))
1572
+ ([x y z & args] (boolean (and (ep1 x y z)
1573
+ (every? p args))))))
1574
+ ([p1 p2]
1575
+ (fn ep2
1576
+ ([] true)
1577
+ ([x] (boolean (and (p1 x) (p2 x))))
1578
+ ([x y] (boolean (and (p1 x) (p1 y) (p2 x) (p2 y))))
1579
+ ([x y z] (boolean (and (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z))))
1580
+ ([x y z & args] (boolean (and (ep2 x y z)
1581
+ (every? #(and (p1 %) (p2 %)) args))))))
1582
+ ([p1 p2 p3]
1583
+ (fn ep3
1584
+ ([] true)
1585
+ ([x] (boolean (and (p1 x) (p2 x) (p3 x))))
1586
+ ([x y] (boolean (and (p1 x) (p2 x) (p3 x) (p1 y) (p2 y) (p3 y))))
1587
+ ([x y z] (boolean (and (p1 x) (p2 x) (p3 x) (p1 y) (p2 y) (p3 y) (p1 z) (p2 z) (p3 z))))
1588
+ ([x y z & args] (boolean (and (ep3 x y z)
1589
+ (every? #(and (p1 %) (p2 %) (p3 %)) args))))))
1590
+ ([p1 p2 p3 & ps]
1591
+ (let [ps (list* p1 p2 p3 ps)]
1592
+ (fn epn
1593
+ ([] true)
1594
+ ([x] (every? #(% x) ps))
1595
+ ([x y] (every? #(and (% x) (% y)) ps))
1596
+ ([x y z] (every? #(and (% x) (% y) (% z)) ps))
1597
+ ([x y z & args] (boolean (and (epn x y z)
1598
+ (every? #(every? % args) ps))))))))
1599
+
1600
+ (defn some-fn
1601
+ "Takes a set of predicates and returns a function f that returns the first logical true value
1602
+ returned by one of its composing predicates against any of its arguments, else it returns
1603
+ logical false. Note that f is short-circuiting in that it will stop execution on the first
1604
+ argument that triggers a logical true result against the original predicates."
1605
+ ([p]
1606
+ (fn sp1
1607
+ ([] nil)
1608
+ ([x] (p x))
1609
+ ([x y] (or (p x) (p y)))
1610
+ ([x y z] (or (p x) (p y) (p z)))
1611
+ ([x y z & args] (or (sp1 x y z)
1612
+ (some p args)))))
1613
+ ([p1 p2]
1614
+ (fn sp2
1615
+ ([] nil)
1616
+ ([x] (or (p1 x) (p2 x)))
1617
+ ([x y] (or (p1 x) (p1 y) (p2 x) (p2 y)))
1618
+ ([x y z] (or (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z)))
1619
+ ([x y z & args] (or (sp2 x y z)
1620
+ (some #(or (p1 %) (p2 %)) args)))))
1621
+ ([p1 p2 p3]
1622
+ (fn sp3
1623
+ ([] nil)
1624
+ ([x] (or (p1 x) (p2 x) (p3 x)))
1625
+ ([x y] (or (p1 x) (p2 x) (p3 x) (p1 y) (p2 y) (p3 y)))
1626
+ ([x y z] (or (p1 x) (p2 x) (p3 x) (p1 y) (p2 y) (p3 y) (p1 z) (p2 z) (p3 z)))
1627
+ ([x y z & args] (or (sp3 x y z)
1628
+ (some #(or (p1 %) (p2 %) (p3 %)) args)))))
1629
+ ([p1 p2 p3 & ps]
1630
+ (let [ps (list* p1 p2 p3 ps)]
1631
+ (fn spn
1632
+ ([] nil)
1633
+ ([x] (some #(% x) ps))
1634
+ ([x y] (some #(or (% x) (% y)) ps))
1635
+ ([x y z] (some #(or (% x) (% y) (% z)) ps))
1636
+ ([x y z & args] (or (spn x y z)
1637
+ (some #(some % args) ps)))))))
1638
+
1639
+ (defn map
1640
+ "Returns a lazy sequence consisting of the result of applying f to the
1641
+ set of first items of each coll, followed by applying f to the set
1642
+ of second items in each coll, until any one of the colls is
1643
+ exhausted. Any remaining items in other colls are ignored. Function
1644
+ f should accept number-of-colls arguments."
1645
+ ([f coll]
1646
+ (lazy-seq
1647
+ (when-let [s (seq coll)]
1648
+ (cons (f (first s)) (map f (rest s))))))
1649
+ ([f c1 c2]
1650
+ (lazy-seq
1651
+ (let [s1 (seq c1) s2 (seq c2)]
1652
+ (when (and s1 s2)
1653
+ (cons (f (first s1) (first s2))
1654
+ (map f (rest s1) (rest s2)))))))
1655
+ ([f c1 c2 c3]
1656
+ (lazy-seq
1657
+ (let [s1 (seq c1) s2 (seq c2) s3 (seq c3)]
1658
+ (when (and s1 s2 s3)
1659
+ (cons (f (first s1) (first s2) (first s3))
1660
+ (map f (rest s1) (rest s2) (rest s3)))))))
1661
+ ([f c1 c2 c3 & colls]
1662
+ (let [step (fn step [cs]
1663
+ (lazy-seq
1664
+ (let [ss (map seq cs)]
1665
+ (when (every? identity ss)
1666
+ (cons (map first ss) (step (map rest ss)))))))]
1667
+ (map #(apply f %) (step (conj colls c3 c2 c1))))))
1668
+
1669
+ (defn take
1670
+ "Returns a lazy sequence of the first n items in coll, or all items if
1671
+ there are fewer than n."
1672
+ [n coll]
1673
+ (lazy-seq
1674
+ (when (pos? n)
1675
+ (when-let [s (seq coll)]
1676
+ (cons (first s) (take (dec n) (rest s)))))))
1677
+
1678
+ (defn drop
1679
+ "Returns a lazy sequence of all but the first n items in coll."
1680
+ [n coll]
1681
+ (let [step (fn [n coll]
1682
+ (let [s (seq coll)]
1683
+ (if (and (pos? n) s)
1684
+ (recur (dec n) (rest s))
1685
+ s)))]
1686
+ (lazy-seq (step n coll))))
1687
+
1688
+ (defn drop-last
1689
+ "Return a lazy sequence of all but the last n (default 1) items in coll"
1690
+ ([s] (drop-last 1 s))
1691
+ ([n s] (map (fn [x _] x) s (drop n s))))
1692
+
1693
+ (defn take-last
1694
+ "Returns a seq of the last n items in coll. Depending on the type
1695
+ of coll may be no better than linear time. For vectors, see also subvec."
1696
+ [n coll]
1697
+ (loop [s (seq coll), lead (seq (drop n coll))]
1698
+ (if lead
1699
+ (recur (next s) (next lead))
1700
+ s)))
1701
+
1702
+ (defn drop-while
1703
+ "Returns a lazy sequence of the items in coll starting from the first
1704
+ item for which (pred item) returns nil."
1705
+ [pred coll]
1706
+ (let [step (fn [pred coll]
1707
+ (let [s (seq coll)]
1708
+ (if (and s (pred (first s)))
1709
+ (recur pred (rest s))
1710
+ s)))]
1711
+ (lazy-seq (step pred coll))))
1712
+
1713
+ (defn cycle
1714
+ "Returns a lazy (infinite!) sequence of repetitions of the items in coll."
1715
+ [coll] (lazy-seq
1716
+ (when-let [s (seq coll)]
1717
+ (concat s (cycle s)))))
1718
+
1719
+ (defn split-at
1720
+ "Returns a vector of [(take n coll) (drop n coll)]"
1721
+ [n coll]
1722
+ [(take n coll) (drop n coll)])
1723
+
1724
+ (defn repeat
1725
+ "Returns a lazy (infinite!, or length n if supplied) sequence of xs."
1726
+ ([x] (lazy-seq (cons x (repeat x))))
1727
+ ([n x] (take n (repeat x))))
1728
+
1729
+ (defn replicate
1730
+ "Returns a lazy seq of n xs."
1731
+ [n x] (take n (repeat x)))
1732
+
1733
+ (defn repeatedly
1734
+ "Takes a function of no args, presumably with side effects, and
1735
+ returns an infinite (or length n if supplied) lazy sequence of calls
1736
+ to it"
1737
+ ([f] (lazy-seq (cons (f) (repeatedly f))))
1738
+ ([n f] (take n (repeatedly f))))
1739
+
1740
+ (defn iterate
1741
+ "Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"
1742
+ {:added "1.0"}
1743
+ [f x] (cons x (lazy-seq (iterate f (f x)))))
1744
+
1745
+ (defn interleave
1746
+ "Returns a lazy seq of the first item in each coll, then the second etc."
1747
+ ([c1 c2]
1748
+ (lazy-seq
1749
+ (let [s1 (seq c1) s2 (seq c2)]
1750
+ (when (and s1 s2)
1751
+ (cons (first s1) (cons (first s2)
1752
+ (interleave (rest s1) (rest s2))))))))
1753
+ ([c1 c2 & colls]
1754
+ (lazy-seq
1755
+ (let [ss (map seq (conj colls c2 c1))]
1756
+ (when (every? identity ss)
1757
+ (concat (map first ss) (apply interleave (map rest ss))))))))
1758
+
1759
+ (defn interpose
1760
+ "Returns a lazy seq of the elements of coll separated by sep"
1761
+ [sep coll] (drop 1 (interleave (repeat sep) coll)))
1762
+
1763
+
1764
+
1765
+ (defn- flatten1
1766
+ "Take a collection of collections, and return a lazy seq
1767
+ of items from the inner collection"
1768
+ [colls]
1769
+ (let [cat (fn cat [coll colls]
1770
+ (lazy-seq
1771
+ (if-let [coll (seq coll)]
1772
+ (cons (first coll) (cat (rest coll) colls))
1773
+ (when (seq colls)
1774
+ (cat (first colls) (rest colls))))))]
1775
+ (cat nil colls)))
1776
+
1777
+ (defn mapcat
1778
+ "Returns the result of applying concat to the result of applying map
1779
+ to f and colls. Thus function f should return a collection."
1780
+ ([f coll]
1781
+ (flatten1 (map f coll)))
1782
+ ([f coll & colls]
1783
+ (flatten1 (apply map f coll colls))))
1784
+
1785
+ (defn filter
1786
+ "Returns a lazy sequence of the items in coll for which
1787
+ (pred item) returns true. pred must be free of side-effects."
1788
+ ([pred coll]
1789
+ (lazy-seq
1790
+ (when-let [s (seq coll)]
1791
+ (let [f (first s) r (rest s)]
1792
+ (if (pred f)
1793
+ (cons f (filter pred r))
1794
+ (filter pred r)))))))
1795
+
1796
+ (defn remove
1797
+ "Returns a lazy sequence of the items in coll for which
1798
+ (pred item) returns false. pred must be free of side-effects."
1799
+ [pred coll]
1800
+ (filter (complement pred) coll))
1801
+
1802
+ (defn tree-seq
1803
+ "Returns a lazy sequence of the nodes in a tree, via a depth-first walk.
1804
+ branch? must be a fn of one arg that returns true if passed a node
1805
+ that can have children (but may not). children must be a fn of one
1806
+ arg that returns a sequence of the children. Will only be called on
1807
+ nodes for which branch? returns true. Root is the root node of the
1808
+ tree."
1809
+ [branch? children root]
1810
+ (let [walk (fn walk [node]
1811
+ (lazy-seq
1812
+ (cons node
1813
+ (when (branch? node)
1814
+ (mapcat walk (children node))))))]
1815
+ (walk root)))
1816
+
1817
+ (defn flatten
1818
+ "Takes any nested combination of sequential things (lists, vectors,
1819
+ etc.) and returns their contents as a single, flat sequence.
1820
+ (flatten nil) returns nil."
1821
+ [x]
1822
+ (filter #(not (sequential? %))
1823
+ (rest (tree-seq sequential? seq x))))
1824
+
1825
+ (defn into
1826
+ "Returns a new coll consisting of to-coll with all of the items of
1827
+ from-coll conjoined."
1828
+ [to from]
1829
+ (reduce -conj to from))
1830
+
1831
+ (defn partition
1832
+ "Returns a lazy sequence of lists of n items each, at offsets step
1833
+ apart. If step is not supplied, defaults to n, i.e. the partitions
1834
+ do not overlap. If a pad collection is supplied, use its elements as
1835
+ necessary to complete last partition upto n items. In case there are
1836
+ not enough padding elements, return a partition with less than n items."
1837
+ ([n coll]
1838
+ (partition n n coll))
1839
+ ([n step coll]
1840
+ (lazy-seq
1841
+ (when-let [s (seq coll)]
1842
+ (let [p (take n s)]
1843
+ (when (= n (count p))
1844
+ (cons p (partition n step (drop step s))))))))
1845
+ ([n step pad coll]
1846
+ (lazy-seq
1847
+ (when-let [s (seq coll)]
1848
+ (let [p (take n s)]
1849
+ (if (= n (count p))
1850
+ (cons p (partition n step pad (drop step s)))
1851
+ (list (take n (concat p pad)))))))))
1852
+
1853
+ (defn get-in
1854
+ "Returns the value in a nested associative structure,
1855
+ where ks is a sequence of ke(ys. Returns nil if the key is not present,
1856
+ or the not-found value if supplied."
1857
+ {:added "1.2"
1858
+ :static true}
1859
+ ([m ks]
1860
+ (reduce get m ks))
1861
+ ([m ks not-found]
1862
+ (loop [sentinel lookup-sentinel
1863
+ m m
1864
+ ks (seq ks)]
1865
+ (if ks
1866
+ (let [m (get m (first ks) sentinel)]
1867
+ (if (identical? sentinel m)
1868
+ not-found
1869
+ (recur sentinel m (next ks))))
1870
+ m))))
1871
+
1872
+ (defn assoc-in
1873
+ "Associates a value in a nested associative structure, where ks is a
1874
+ sequence of keys and v is the new value and returns a new nested structure.
1875
+ If any levels do not exist, hash-maps will be created."
1876
+ [m [k & ks] v]
1877
+ (if ks
1878
+ (assoc m k (assoc-in (get m k) ks v))
1879
+ (assoc m k v)))
1880
+
1881
+ (defn update-in
1882
+ "'Updates' a value in a nested associative structure, where ks is a
1883
+ sequence of keys and f is a function that will take the old value
1884
+ and any supplied args and return the new value, and returns a new
1885
+ nested structure. If any levels do not exist, hash-maps will be
1886
+ created."
1887
+ ([m [k & ks] f & args]
1888
+ (if ks
1889
+ (assoc m k (apply update-in (get m k) ks f args))
1890
+ (assoc m k (apply f (get m k) args)))))
1891
+
1892
+
1893
+ ;;; Vector
1894
+
1895
+ (deftype Vector [meta array]
1896
+ IWithMeta
1897
+ (-with-meta [coll meta] (Vector. meta array))
1898
+
1899
+ IMeta
1900
+ (-meta [coll] meta)
1901
+
1902
+ IStack
1903
+ (-peek [coll]
1904
+ (let [count (.length array)]
1905
+ (when (> count 0)
1906
+ (aget array (dec count)))))
1907
+ (-pop [coll]
1908
+ (if (> (.length array) 0)
1909
+ (let [new-array (aclone array)]
1910
+ (. new-array (pop))
1911
+ (Vector. meta new-array))
1912
+ (throw (js/Error. "Can't pop empty vector"))))
1913
+
1914
+ ICollection
1915
+ (-conj [coll o]
1916
+ (let [new-array (aclone array)]
1917
+ (.push new-array o)
1918
+ (Vector. meta new-array)))
1919
+
1920
+ IEmptyableCollection
1921
+ (-empty [coll] (with-meta cljs.core.Vector/EMPTY meta))
1922
+
1923
+ ISequential
1924
+ IEquiv
1925
+ (-equiv [coll other] (equiv-sequential coll other))
1926
+
1927
+ IHash
1928
+ (-hash [coll] (hash-coll coll))
1929
+
1930
+ ISeqable
1931
+ (-seq [coll]
1932
+ (when (> (.length array) 0)
1933
+ (let [vector-seq
1934
+ (fn vector-seq [i]
1935
+ (lazy-seq
1936
+ (when (< i (.length array))
1937
+ (cons (aget array i) (vector-seq (inc i))))))]
1938
+ (vector-seq 0))))
1939
+
1940
+ ICounted
1941
+ (-count [coll] (.length array))
1942
+
1943
+ IIndexed
1944
+ (-nth [coll n]
1945
+ (if (and (<= 0 n) (< n (.length array)))
1946
+ (aget array n)
1947
+ #_(throw (js/Error. (str "No item " n " in vector of length " (.length array))))))
1948
+ (-nth [coll n not-found]
1949
+ (if (and (<= 0 n) (< n (.length array)))
1950
+ (aget array n)
1951
+ not-found))
1952
+
1953
+ ILookup
1954
+ (-lookup [coll k] (-nth coll k nil))
1955
+ (-lookup [coll k not-found] (-nth coll k not-found))
1956
+
1957
+ IAssociative
1958
+ (-assoc [coll k v]
1959
+ (let [new-array (aclone array)]
1960
+ (aset new-array k v)
1961
+ (Vector. meta new-array)))
1962
+
1963
+ IVector
1964
+ (-assoc-n [coll n val] (-assoc coll n val))
1965
+
1966
+ IReduce
1967
+ (-reduce [v f]
1968
+ (ci-reduce array f))
1969
+ (-reduce [v f start]
1970
+ (ci-reduce array f start)))
1971
+
1972
+ (set! cljs.core.Vector/EMPTY (Vector. nil (array)))
1973
+
1974
+ (set! cljs.core.Vector/fromArray (fn [xs] (Vector. nil xs)))
1975
+
1976
+ (set! cljs.core.Vector.prototype.call
1977
+ (fn
1978
+ ([_ k] (-lookup (js* "this") k))
1979
+ ([_ k not-found] (-lookup (js* "this") k not-found))))
1980
+
1981
+ (defn vec [coll]
1982
+ (reduce conj cljs.core.Vector/EMPTY coll)) ; using [] here causes infinite recursion
1983
+
1984
+ (defn vector [& args] (vec args))
1985
+
1986
+ (deftype NeverEquiv []
1987
+ IEquiv
1988
+ (-equiv [o other] false))
1989
+
1990
+ (def ^:private never-equiv (NeverEquiv.))
1991
+
1992
+ (defn- equiv-map
1993
+ "Assumes y is a map. Returns true if x equals y, otherwise returns
1994
+ false."
1995
+ [x y]
1996
+ (boolean
1997
+ (when (map? y)
1998
+ ; assume all maps are counted
1999
+ (when (= (count x) (count y))
2000
+ (every? identity
2001
+ (map (fn [xkv] (= (get y (first xkv) never-equiv)
2002
+ (second xkv)))
2003
+ x))))))
2004
+
2005
+
2006
+ (defn- scan-array [incr k array]
2007
+ (let [len (.length array)]
2008
+ (loop [i 0]
2009
+ (when (< i len)
2010
+ (if (= k (aget array i))
2011
+ i
2012
+ (recur (+ i incr)))))))
2013
+
2014
+ ; The keys field is an array of all keys of this map, in no particular
2015
+ ; order. Any string, keyword, or symbol key is used as a property name
2016
+ ; to store the value in strobj. If a key is assoc'ed when that same
2017
+ ; key already exists in strobj, the old value is overwritten. If a
2018
+ ; non-string key is assoc'ed, return a HashMap object instead.
2019
+
2020
+ (defn- obj-map-contains-key?
2021
+ ([k strobj]
2022
+ (obj-map-contains-key? k strobj true false))
2023
+ ([k strobj true-val false-val]
2024
+ (if (and (goog/isString k) (.hasOwnProperty strobj k))
2025
+ true-val
2026
+ false-val)))
2027
+
2028
+ (declare hash-map)
2029
+ (deftype ObjMap [meta keys strobj]
2030
+ IWithMeta
2031
+ (-with-meta [coll meta] (ObjMap. meta keys strobj))
2032
+
2033
+ IMeta
2034
+ (-meta [coll] meta)
2035
+
2036
+ ICollection
2037
+ (-conj [coll entry]
2038
+ (if (vector? entry)
2039
+ (-assoc coll (-nth entry 0) (-nth entry 1))
2040
+ (reduce -conj
2041
+ coll
2042
+ entry)))
2043
+
2044
+ IEmptyableCollection
2045
+ (-empty [coll] (with-meta cljs.core.ObjMap/EMPTY meta))
2046
+
2047
+ IEquiv
2048
+ (-equiv [coll other] (equiv-map coll other))
2049
+
2050
+ IHash
2051
+ (-hash [coll] (hash-coll coll))
2052
+
2053
+ ISeqable
2054
+ (-seq [coll]
2055
+ (when (pos? (.length keys))
2056
+ (map #(vector % (aget strobj %)) keys)))
2057
+
2058
+ ICounted
2059
+ (-count [coll] (.length keys))
2060
+
2061
+ ILookup
2062
+ (-lookup [coll k] (-lookup coll k nil))
2063
+ (-lookup [coll k not-found]
2064
+ (obj-map-contains-key? k strobj (aget strobj k) not-found))
2065
+
2066
+ IAssociative
2067
+ (-assoc [coll k v]
2068
+ (if (goog/isString k)
2069
+ (let [new-strobj (goog.object/clone strobj)
2070
+ overwrite? (.hasOwnProperty new-strobj k)]
2071
+ (aset new-strobj k v)
2072
+ (if overwrite?
2073
+ (ObjMap. meta keys new-strobj) ; overwrite
2074
+ (let [new-keys (aclone keys)] ; append
2075
+ (.push new-keys k)
2076
+ (ObjMap. meta new-keys new-strobj))))
2077
+ ; non-string key. game over.
2078
+ (with-meta (into (hash-map k v) (seq coll)) meta)))
2079
+ (-contains-key? [coll k]
2080
+ (obj-map-contains-key? k strobj))
2081
+
2082
+ IMap
2083
+ (-dissoc [coll k]
2084
+ (if (and (goog/isString k) (.hasOwnProperty strobj k))
2085
+ (let [new-keys (aclone keys)
2086
+ new-strobj (goog.object/clone strobj)]
2087
+ (.splice new-keys (scan-array 1 k new-keys) 1)
2088
+ (js-delete new-strobj k)
2089
+ (ObjMap. meta new-keys new-strobj))
2090
+ coll))) ; key not found, return coll unchanged
2091
+
2092
+ (set! cljs.core.ObjMap/EMPTY (ObjMap. nil (array) (js-obj)))
2093
+
2094
+ (set! cljs.core.ObjMap/fromObject (fn [ks obj] (ObjMap. nil ks obj)))
2095
+
2096
+ (set! cljs.core.ObjMap.prototype.call
2097
+ (fn
2098
+ ([_ k] (-lookup (js* "this") k))
2099
+ ([_ k not-found] (-lookup (js* "this") k not-found))))
2100
+
2101
+ ; The keys field is an array of all keys of this map, in no particular
2102
+ ; order. Each key is hashed and the result used as a property name of
2103
+ ; hashobj. Each values in hashobj is actually a bucket in order to handle hash
2104
+ ; collisions. A bucket is an array of alternating keys (not their hashes) and
2105
+ ; vals.
2106
+ (deftype HashMap [meta count hashobj]
2107
+ IWithMeta
2108
+ (-with-meta [coll meta] (HashMap. meta count hashobj))
2109
+
2110
+ IMeta
2111
+ (-meta [coll] meta)
2112
+
2113
+ ICollection
2114
+ (-conj [coll entry]
2115
+ (if (vector? entry)
2116
+ (-assoc coll (-nth entry 0) (-nth entry 1))
2117
+ (reduce -conj
2118
+ coll
2119
+ entry)))
2120
+
2121
+ IEmptyableCollection
2122
+ (-empty [coll] (with-meta cljs.core.HashMap/EMPTY meta))
2123
+
2124
+ IEquiv
2125
+ (-equiv [coll other] (equiv-map coll other))
2126
+
2127
+ IHash
2128
+ (-hash [coll] (hash-coll coll))
2129
+
2130
+ ISeqable
2131
+ (-seq [coll]
2132
+ (when (pos? count)
2133
+ (let [hashes (js-keys hashobj)]
2134
+ (mapcat #(map vec (partition 2 (aget hashobj %)))
2135
+ hashes))))
2136
+
2137
+ ICounted
2138
+ (-count [coll] count)
2139
+
2140
+ ILookup
2141
+ (-lookup [coll k] (-lookup coll k nil))
2142
+ (-lookup [coll k not-found]
2143
+ (let [bucket (aget hashobj (hash k))
2144
+ i (when bucket (scan-array 2 k bucket))]
2145
+ (if i
2146
+ (aget bucket (inc i))
2147
+ not-found)))
2148
+
2149
+ IAssociative
2150
+ (-assoc [coll k v]
2151
+ (let [h (hash k)
2152
+ bucket (aget hashobj h)]
2153
+ (if bucket
2154
+ (let [new-bucket (aclone bucket)
2155
+ new-hashobj (goog.object/clone hashobj)]
2156
+ (aset new-hashobj h new-bucket)
2157
+ (if-let [i (scan-array 2 k new-bucket)]
2158
+ (do ; found key, replace
2159
+ (aset new-bucket (inc i) v)
2160
+ (HashMap. meta count new-hashobj))
2161
+ (do ; did not find key, append
2162
+ (.push new-bucket k v)
2163
+ (HashMap. meta (inc count) new-hashobj))))
2164
+ (let [new-hashobj (goog.object/clone hashobj)] ; did not find bucket
2165
+ (aset new-hashobj h (array k v))
2166
+ (HashMap. meta (inc count) new-hashobj)))))
2167
+ (-contains-key? [coll k]
2168
+ (let [bucket (aget hashobj (hash k))
2169
+ i (when bucket (scan-array 2 k bucket))]
2170
+ (if i
2171
+ true
2172
+ false)))
2173
+
2174
+ IMap
2175
+ (-dissoc [coll k]
2176
+ (let [h (hash k)
2177
+ bucket (aget hashobj h)
2178
+ i (when bucket (scan-array 2 k bucket))]
2179
+ (if (not i)
2180
+ coll ; key not found, return coll unchanged
2181
+ (let [new-hashobj (goog.object/clone hashobj)]
2182
+ (if (> 3 (.length bucket))
2183
+ (js-delete new-hashobj h)
2184
+ (let [new-bucket (aclone bucket)]
2185
+ (.splice new-bucket i 2)
2186
+ (aset new-hashobj h new-bucket)))
2187
+ (HashMap. meta (dec count) new-hashobj))))))
2188
+
2189
+ (set! cljs.core.HashMap/EMPTY (HashMap. nil 0 (js-obj)))
2190
+
2191
+ (set! cljs.core.HashMap/fromArrays (fn [ks vs]
2192
+ (let [len (.length ks)]
2193
+ (loop [i 0, out cljs.core.HashMap/EMPTY]
2194
+ (if (< i len)
2195
+ (recur (inc i) (assoc out (aget ks i) (aget vs i)))
2196
+ out)))))
2197
+
2198
+ (set! cljs.core.HashMap.prototype.call
2199
+ (fn
2200
+ ([_ k] (-lookup (js* "this") k))
2201
+ ([_ k not-found] (-lookup (js* "this") k not-found))))
2202
+
2203
+ (defn hash-map
2204
+ "keyval => key val
2205
+ Returns a new hash map with supplied mappings."
2206
+ [& keyvals]
2207
+ (loop [in (seq keyvals), out cljs.core.HashMap/EMPTY]
2208
+ (if in
2209
+ (recur (nnext in) (assoc out (first in) (second in)))
2210
+ out)))
2211
+
2212
+ (defn keys
2213
+ "Returns a sequence of the map's keys."
2214
+ [hash-map]
2215
+ (seq (map first hash-map)))
2216
+
2217
+ (defn vals
2218
+ "Returns a sequence of the map's values."
2219
+ [hash-map]
2220
+ (seq (map second hash-map)))
2221
+
2222
+ (defn merge
2223
+ "Returns a map that consists of the rest of the maps conj-ed onto
2224
+ the first. If a key occurs in more than one map, the mapping from
2225
+ the latter (left-to-right) will be the mapping in the result."
2226
+ [& maps]
2227
+ (when (some identity maps)
2228
+ (reduce #(conj (or %1 {}) %2) maps)))
2229
+
2230
+ (defn merge-with
2231
+ "Returns a map that consists of the rest of the maps conj-ed onto
2232
+ the first. If a key occurs in more than one map, the mapping(s)
2233
+ from the latter (left-to-right) will be combined with the mapping in
2234
+ the result by calling (f val-in-result val-in-latter)."
2235
+ [f & maps]
2236
+ (when (some identity maps)
2237
+ (let [merge-entry (fn [m e]
2238
+ (let [k (first e) v (second e)]
2239
+ (if (contains? m k)
2240
+ (assoc m k (f (get m k) v))
2241
+ (assoc m k v))))
2242
+ merge2 (fn [m1 m2]
2243
+ (reduce merge-entry (or m1 {}) (seq m2)))]
2244
+ (reduce merge2 maps))))
2245
+
2246
+ (defn select-keys
2247
+ "Returns a map containing only those entries in map whose key is in keys"
2248
+ [map keyseq]
2249
+ (loop [ret {} keys (seq keyseq)]
2250
+ (if keys
2251
+ (let [key (first keys)
2252
+ entry (get map key ::not-found)]
2253
+ (recur
2254
+ (if (not= entry ::not-found)
2255
+ (assoc ret key entry)
2256
+ ret)
2257
+ (next keys)))
2258
+ ret)))
2259
+
2260
+ ;;; Set
2261
+
2262
+ (deftype Set [meta hash-map]
2263
+ IWithMeta
2264
+ (-with-meta [coll meta] (Set. meta hash-map))
2265
+
2266
+ IMeta
2267
+ (-meta [coll] meta)
2268
+
2269
+ ICollection
2270
+ (-conj [coll o]
2271
+ (Set. meta (assoc hash-map o nil)))
2272
+
2273
+ IEmptyableCollection
2274
+ (-empty [coll] (with-meta cljs.core.Set/EMPTY meta))
2275
+
2276
+ IEquiv
2277
+ (-equiv [coll other]
2278
+ (and
2279
+ (set? other)
2280
+ (= (count coll) (count other))
2281
+ (every? #(contains? coll %)
2282
+ other)))
2283
+
2284
+ IHash
2285
+ (-hash [coll] (hash-coll coll))
2286
+
2287
+ ISeqable
2288
+ (-seq [coll] (keys hash-map))
2289
+
2290
+ ICounted
2291
+ (-count [coll] (count (seq coll)))
2292
+
2293
+ ILookup
2294
+ (-lookup [coll v]
2295
+ (-lookup coll v nil))
2296
+ (-lookup [coll v not-found]
2297
+ (if (-contains-key? hash-map v)
2298
+ v
2299
+ not-found))
2300
+
2301
+ ISet
2302
+ (-disjoin [coll v]
2303
+ (Set. meta (dissoc hash-map v))))
2304
+
2305
+ (set! cljs.core.Set/EMPTY (Set. nil (hash-map)))
2306
+
2307
+ (set! cljs.core.Set.prototype.call
2308
+ (fn
2309
+ ([_ k] (-lookup (js* "this") k))
2310
+ ([_ k not-found] (-lookup (js* "this") k not-found))))
2311
+
2312
+ (defn set
2313
+ "Returns a set of the distinct elements of coll."
2314
+ [coll]
2315
+ (loop [in (seq coll)
2316
+ out cljs.core.Set/EMPTY]
2317
+ (if-not (empty? in)
2318
+ (recur (rest in) (conj out (first in)))
2319
+ out)))
2320
+
2321
+ (defn replace
2322
+ "Given a map of replacement pairs and a vector/collection, returns a
2323
+ vector/seq with any elements = a key in smap replaced with the
2324
+ corresponding val in smap"
2325
+ [smap coll]
2326
+ (if (vector? coll)
2327
+ (let [n (count coll)]
2328
+ (reduce (fn [v i]
2329
+ (if-let [e (find smap (nth v i))]
2330
+ (assoc v i (second e))
2331
+ v))
2332
+ coll (take n (iterate inc 0))))
2333
+ (map #(if-let [e (find smap %)] (second e) %) coll)))
2334
+
2335
+ (defn distinct
2336
+ "Returns a lazy sequence of the elements of coll with duplicates removed"
2337
+ [coll]
2338
+ (let [step (fn step [xs seen]
2339
+ (lazy-seq
2340
+ ((fn [[f :as xs] seen]
2341
+ (when-let [s (seq xs)]
2342
+ (if (contains? seen f)
2343
+ (recur (rest s) seen)
2344
+ (cons f (step (rest s) (conj seen f))))))
2345
+ xs seen)))]
2346
+ (step coll #{})))
2347
+
2348
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2349
+ (defn butlast [s]
2350
+ (loop [ret [] s s]
2351
+ (if (next s)
2352
+ (recur (conj ret (first s)) (next s))
2353
+ (seq ret))))
2354
+
2355
+ (defn name
2356
+ "Returns the name String of a string, symbol or keyword."
2357
+ [x]
2358
+ (cond
2359
+ (string? x) x
2360
+ (or (keyword? x) (symbol? x))
2361
+ (let [i (.lastIndexOf x "/")]
2362
+ (if (< i 0)
2363
+ (subs x 2)
2364
+ (subs x (inc i))))
2365
+ :else (throw (js/Error. (str "Doesn't support name: " x)))))
2366
+
2367
+ (defn namespace
2368
+ "Returns the namespace String of a symbol or keyword, or nil if not present."
2369
+ [x]
2370
+ (if (or (keyword? x) (symbol? x))
2371
+ (let [i (.lastIndexOf x "/")]
2372
+ (when (> i -1)
2373
+ (subs x 2 i)))
2374
+ (throw (js/Error. (str "Doesn't support namespace: " x)))))
2375
+
2376
+ (defn zipmap
2377
+ "Returns a map with the keys mapped to the corresponding vals."
2378
+ [keys vals]
2379
+ (loop [map {}
2380
+ ks (seq keys)
2381
+ vs (seq vals)]
2382
+ (if (and ks vs)
2383
+ (recur (assoc map (first ks) (first vs))
2384
+ (next ks)
2385
+ (next vs))
2386
+ map)))
2387
+
2388
+ (defn max-key
2389
+ "Returns the x for which (k x), a number, is greatest."
2390
+ ([k x] x)
2391
+ ([k x y] (if (> (k x) (k y)) x y))
2392
+ ([k x y & more]
2393
+ (reduce #(max-key k %1 %2) (max-key k x y) more)))
2394
+
2395
+ (defn min-key
2396
+ "Returns the x for which (k x), a number, is least."
2397
+ ([k x] x)
2398
+ ([k x y] (if (< (k x) (k y)) x y))
2399
+ ([k x y & more]
2400
+ (reduce #(min-key k %1 %2) (min-key k x y) more)))
2401
+
2402
+ (defn partition-all
2403
+ "Returns a lazy sequence of lists like partition, but may include
2404
+ partitions with fewer than n items at the end."
2405
+ ([n coll]
2406
+ (partition-all n n coll))
2407
+ ([n step coll]
2408
+ (lazy-seq
2409
+ (when-let [s (seq coll)]
2410
+ (cons (take n s) (partition-all n step (drop step s)))))))
2411
+
2412
+ (defn take-while
2413
+ "Returns a lazy sequence of successive items from coll while
2414
+ (pred item) returns true. pred must be free of side-effects."
2415
+ [pred coll]
2416
+ (lazy-seq
2417
+ (when-let [s (seq coll)]
2418
+ (when (pred (first s))
2419
+ (cons (first s) (take-while pred (rest s)))))))
2420
+
2421
+ (deftype Range [meta start end step]
2422
+ IWithMeta
2423
+ (-with-meta [rng meta] (Range. meta start end step))
2424
+
2425
+ IMeta
2426
+ (-meta [rng] meta)
2427
+
2428
+ ISeq
2429
+ (-first [rng] start)
2430
+
2431
+ (-rest [rng]
2432
+ (if (-seq rng)
2433
+ (Range. meta (+ start step) end step)
2434
+ (list)))
2435
+
2436
+ ICollection
2437
+ (-conj [rng o] (cons o rng))
2438
+
2439
+ IEmptyableCollection
2440
+ (-empty [rng] (with-meta cljs.core.List/EMPTY meta))
2441
+
2442
+ ISequential
2443
+ IEquiv
2444
+ (-equiv [rng other] (equiv-sequential rng other))
2445
+
2446
+ IHash
2447
+ (-hash [rng] (hash-coll rng))
2448
+
2449
+ ICounted
2450
+ (-count [rng]
2451
+ (if-not (-seq rng)
2452
+ 0
2453
+ (js/Math.ceil (/ (- end start) step))))
2454
+
2455
+ IIndexed
2456
+ (-nth [rng n]
2457
+ (if (< n (-count rng))
2458
+ (+ start (* n step))
2459
+ (if (and (> start end) (= step 0))
2460
+ start
2461
+ (throw (js/Error. "Index out of bounds")))))
2462
+ (-nth [rng n not-found]
2463
+ (if (< n (-count rng))
2464
+ (+ start (* n step))
2465
+ (if (and (> start end) (= step 0))
2466
+ start
2467
+ not-found)))
2468
+
2469
+ ISeqable
2470
+ (-seq [rng]
2471
+ (let [comp (if (pos? step) < >)]
2472
+ (when (comp start end)
2473
+ rng)))
2474
+
2475
+ IReduce
2476
+ (-reduce [rng f] (ci-reduce rng f))
2477
+ (-reduce [rng f s] (ci-reduce rng f s)))
2478
+
2479
+ (defn range
2480
+ "Returns a lazy seq of nums from start (inclusive) to end
2481
+ (exclusive), by step, where start defaults to 0, step to 1,
2482
+ and end to infinity."
2483
+ ([] (range 0 js/Number.MAX_VALUE 1))
2484
+ ([end] (range 0 end 1))
2485
+ ([start end] (range start end 1))
2486
+ ([start end step] (Range. nil start end step)))
2487
+
2488
+ (defn take-nth
2489
+ "Returns a lazy seq of every nth item in coll."
2490
+ [n coll]
2491
+ (lazy-seq
2492
+ (when-let [s (seq coll)]
2493
+ (cons (first s) (take-nth n (drop n s))))))
2494
+
2495
+ (defn split-with
2496
+ "Returns a vector of [(take-while pred coll) (drop-while pred coll)]"
2497
+ [pred coll]
2498
+ [(take-while pred coll) (drop-while pred coll)])
2499
+
2500
+ (defn partition-by
2501
+ "Applies f to each value in coll, splitting it each time f returns
2502
+ a new value. Returns a lazy seq of partitions."
2503
+ [f coll]
2504
+ (lazy-seq
2505
+ (when-let [s (seq coll)]
2506
+ (let [fst (first s)
2507
+ fv (f fst)
2508
+ run (cons fst (take-while #(= fv (f %)) (next s)))]
2509
+ (cons run (partition-by f (seq (drop (count run) s))))))))
2510
+
2511
+ (defn frequencies
2512
+ "Returns a map from distinct items in coll to the number of times
2513
+ they appear."
2514
+ [coll]
2515
+ (reduce
2516
+ (fn [counts x]
2517
+ (assoc counts x (inc (get counts x 0))))
2518
+ {}
2519
+ coll))
2520
+
2521
+ (defn reductions
2522
+ "Returns a lazy seq of the intermediate values of the reduction (as
2523
+ per reduce) of coll by f, starting with init."
2524
+ ([f coll]
2525
+ (lazy-seq
2526
+ (if-let [s (seq coll)]
2527
+ (reductions f (first s) (rest s))
2528
+ (list (f)))))
2529
+ ([f init coll]
2530
+ (cons init
2531
+ (lazy-seq
2532
+ (when-let [s (seq coll)]
2533
+ (reductions f (f init (first s)) (rest s)))))))
2534
+
2535
+ (defn juxt
2536
+ "Takes a set of functions and returns a fn that is the juxtaposition
2537
+ of those fns. The returned fn takes a variable number of args, and
2538
+ returns a vector containing the result of applying each fn to the
2539
+ args (left-to-right).
2540
+ ((juxt a b c) x) => [(a x) (b x) (c x)]
2541
+
2542
+ TODO: Implement apply"
2543
+ ([f]
2544
+ (fn
2545
+ ([] (vector (f)))
2546
+ ([x] (vector (f x)))
2547
+ ([x y] (vector (f x y)))
2548
+ ([x y z] (vector (f x y z)))
2549
+ ([x y z & args] (vector (apply f x y z args)))))
2550
+ ([f g]
2551
+ (fn
2552
+ ([] (vector (f) (g)))
2553
+ ([x] (vector (f x) (g x)))
2554
+ ([x y] (vector (f x y) (g x y)))
2555
+ ([x y z] (vector (f x y z) (g x y z)))
2556
+ ([x y z & args] (vector (apply f x y z args) (apply g x y z args)))))
2557
+ ([f g h]
2558
+ (fn
2559
+ ([] (vector (f) (g) (h)))
2560
+ ([x] (vector (f x) (g x) (h x)))
2561
+ ([x y] (vector (f x y) (g x y) (h x y)))
2562
+ ([x y z] (vector (f x y z) (g x y z) (h x y z)))
2563
+ ([x y z & args] (vector (apply f x y z args) (apply g x y z args) (apply h x y z args)))))
2564
+ ([f g h & fs]
2565
+ (let [fs (list* f g h fs)]
2566
+ (fn
2567
+ ([] (reduce #(conj %1 (%2)) [] fs))
2568
+ ([x] (reduce #(conj %1 (%2 x)) [] fs))
2569
+ ([x y] (reduce #(conj %1 (%2 x y)) [] fs))
2570
+ ([x y z] (reduce #(conj %1 (%2 x y z)) [] fs))
2571
+ ([x y z & args] (reduce #(conj %1 (apply %2 x y z args)) [] fs))))))
2572
+
2573
+ (defn dorun
2574
+ "When lazy sequences are produced via functions that have side
2575
+ effects, any effects other than those needed to produce the first
2576
+ element in the seq do not occur until the seq is consumed. dorun can
2577
+ be used to force any effects. Walks through the successive nexts of
2578
+ the seq, does not retain the head and returns nil."
2579
+ ([coll]
2580
+ (when (seq coll)
2581
+ (recur (next coll))))
2582
+ ([n coll]
2583
+ (when (and (seq coll) (pos? n))
2584
+ (recur (dec n) (next coll)))))
2585
+
2586
+ (defn doall
2587
+ "When lazy sequences are produced via functions that have side
2588
+ effects, any effects other than those needed to produce the first
2589
+ element in the seq do not occur until the seq is consumed. doall can
2590
+ be used to force any effects. Walks through the successive nexts of
2591
+ the seq, retains the head and returns it, thus causing the entire
2592
+ seq to reside in memory at one time."
2593
+ ([coll]
2594
+ (dorun coll)
2595
+ coll)
2596
+ ([n coll]
2597
+ (dorun n coll)
2598
+ coll))
2599
+
2600
+ ;;;;;;;;;;;;;;;;;;;;;;;;; Regular Expressions ;;;;;;;;;;
2601
+
2602
+ (defn re-matches
2603
+ "Returns the result of (re-find re s) if re fully matches s."
2604
+ [re s]
2605
+ (let [matches (.exec re s)]
2606
+ (when (= (first matches) s)
2607
+ (if (= (count matches) 1)
2608
+ (first matches)
2609
+ (vec matches)))))
2610
+
2611
+ (defn re-find
2612
+ "Returns the first regex match, if any, of s to re, using
2613
+ re.exec(s). Returns a vector, containing first the matching
2614
+ substring, then any capturing groups if the regular expression contains
2615
+ capturing groups."
2616
+ [re s]
2617
+ (let [matches (.exec re s)]
2618
+ (when-not (nil? matches)
2619
+ (if (= (count matches) 1)
2620
+ (first matches)
2621
+ (vec matches)))))
2622
+
2623
+ (defn re-seq
2624
+ "Returns a lazy sequence of successive matches of re in s."
2625
+ [re s]
2626
+ (let [match-data (re-find re s)
2627
+ match-idx (.search s re)
2628
+ match-str (if (coll? match-data) (first match-data) match-data)
2629
+ post-match (subs s (+ match-idx (count match-str)))]
2630
+ (when match-data (lazy-seq (cons match-data (re-seq re post-match))))))
2631
+
2632
+ (defn re-pattern
2633
+ "Returns an instance of RegExp which has compiled the provided string."
2634
+ [s]
2635
+ (js/RegExp. s))
2636
+
2637
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Printing ;;;;;;;;;;;;;;;;
2638
+
2639
+ (defn pr-sequential [print-one begin sep end opts coll]
2640
+ (concat [begin]
2641
+ (flatten1
2642
+ (interpose [sep] (map #(print-one % opts) coll)))
2643
+ [end]))
2644
+
2645
+ (defn string-print [x]
2646
+ (*print-fn* x)
2647
+ nil)
2648
+
2649
+ (defn flush [] ;stub
2650
+ nil)
2651
+
2652
+ (defn- pr-seq [obj opts]
2653
+ (cond
2654
+ (nil? obj) (list "nil")
2655
+ (undefined? obj) (list "#<undefined>")
2656
+ :else (concat
2657
+ (when (and (get opts :meta)
2658
+ (satisfies? IMeta obj)
2659
+ (meta obj))
2660
+ (concat ["^"] (pr-seq (meta obj) opts) [" "]))
2661
+ (if (satisfies? IPrintable obj)
2662
+ (-pr-seq obj opts)
2663
+ (list "#<" (str obj) ">")))))
2664
+
2665
+ (defn pr-str-with-opts
2666
+ "Prints a sequence of objects to a string, observing all the
2667
+ options given in opts"
2668
+ [objs opts]
2669
+ (let [first-obj (first objs)
2670
+ sb (gstring/StringBuffer.)]
2671
+ (doseq [obj objs]
2672
+ (when-not (identical? obj first-obj)
2673
+ (.append sb " "))
2674
+ (doseq [string (pr-seq obj opts)]
2675
+ (.append sb string)))
2676
+ (str sb)))
2677
+
2678
+ (defn pr-with-opts
2679
+ "Prints a sequence of objects using string-print, observing all
2680
+ the options given in opts"
2681
+ [objs opts]
2682
+ (let [first-obj (first objs)]
2683
+ (doseq [obj objs]
2684
+ (when-not (identical? obj first-obj)
2685
+ (string-print " "))
2686
+ (doseq [string (pr-seq obj opts)]
2687
+ (string-print string)))))
2688
+
2689
+ (defn newline [opts]
2690
+ (string-print "\n")
2691
+ (when (get opts :flush-on-newline)
2692
+ (flush)))
2693
+
2694
+ (def *flush-on-newline* true)
2695
+ (def *print-readably* true)
2696
+ (def *print-meta* false)
2697
+ (def *print-dup* false)
2698
+
2699
+ (defn- pr-opts []
2700
+ {:flush-on-newline *flush-on-newline*
2701
+ :readably *print-readably*
2702
+ :meta *print-meta*
2703
+ :dup *print-dup*})
2704
+
2705
+ (defn pr-str
2706
+ "pr to a string, returning it. Fundamental entrypoint to IPrintable."
2707
+ [& objs]
2708
+ (pr-str-with-opts objs (pr-opts)))
2709
+
2710
+ (defn pr
2711
+ "Prints the object(s) using string-print. Prints the
2712
+ object(s), separated by spaces if there is more than one.
2713
+ By default, pr and prn print in a way that objects can be
2714
+ read by the reader"
2715
+ [& objs]
2716
+ (pr-with-opts objs (pr-opts)))
2717
+
2718
+ (def ^{:doc
2719
+ "Prints the object(s) using string-print.
2720
+ print and println produce output for human consumption."}
2721
+ print
2722
+ (fn cljs-core-print [& objs]
2723
+ (pr-with-opts objs (assoc (pr-opts) :readably false))))
2724
+
2725
+ (defn println
2726
+ "Same as print followed by (newline)"
2727
+ [& objs]
2728
+ (pr-with-opts objs (assoc (pr-opts) :readably false))
2729
+ (newline (pr-opts)))
2730
+
2731
+ (defn prn
2732
+ "Same as pr followed by (newline)."
2733
+ [& objs]
2734
+ (pr-with-opts objs (pr-opts))
2735
+ (newline (pr-opts)))
2736
+
2737
+ (extend-protocol IPrintable
2738
+ boolean
2739
+ (-pr-seq [bool opts] (list (str bool)))
2740
+
2741
+ number
2742
+ (-pr-seq [n opts] (list (str n)))
2743
+
2744
+ array
2745
+ (-pr-seq [a opts]
2746
+ (pr-sequential pr-seq "#<Array [" ", " "]>" opts a))
2747
+
2748
+ string
2749
+ (-pr-seq [obj opts]
2750
+ (cond
2751
+ (keyword? obj)
2752
+ (list (str ":"
2753
+ (when-let [nspc (namespace obj)]
2754
+ (str nspc "/"))
2755
+ (name obj)))
2756
+ (symbol? obj)
2757
+ (list (str (when-let [nspc (namespace obj)]
2758
+ (str nspc "/"))
2759
+ (name obj)))
2760
+ :else (list (if (:readably opts)
2761
+ (goog.string.quote obj)
2762
+ obj))))
2763
+
2764
+ LazySeq
2765
+ (-pr-seq [coll opts] (pr-sequential pr-seq "(" " " ")" opts coll))
2766
+
2767
+ IndexedSeq
2768
+ (-pr-seq [coll opts] (pr-sequential pr-seq "(" " " ")" opts coll))
2769
+
2770
+ List
2771
+ (-pr-seq [coll opts] (pr-sequential pr-seq "(" " " ")" opts coll))
2772
+
2773
+ Cons
2774
+ (-pr-seq [coll opts] (pr-sequential pr-seq "(" " " ")" opts coll))
2775
+
2776
+ EmptyList
2777
+ (-pr-seq [coll opts] (list "()"))
2778
+
2779
+ Vector
2780
+ (-pr-seq [coll opts] (pr-sequential pr-seq "[" " " "]" opts coll))
2781
+
2782
+ ObjMap
2783
+ (-pr-seq [coll opts]
2784
+ (let [pr-pair (fn [keyval] (pr-sequential pr-seq "" " " "" opts keyval))]
2785
+ (pr-sequential pr-pair "{" ", " "}" opts coll)))
2786
+
2787
+ HashMap
2788
+ (-pr-seq [coll opts]
2789
+ (let [pr-pair (fn [keyval] (pr-sequential pr-seq "" " " "" opts keyval))]
2790
+ (pr-sequential pr-pair "{" ", " "}" opts coll)))
2791
+
2792
+ Set
2793
+ (-pr-seq [coll opts] (pr-sequential pr-seq "#{" " " "}" opts coll))
2794
+
2795
+ Range
2796
+ (-pr-seq [coll opts] (pr-sequential pr-seq "(" " " ")" opts coll)))
2797
+
2798
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Reference Types ;;;;;;;;;;;;;;;;
2799
+
2800
+ (deftype Atom [state meta validator watches]
2801
+ IEquiv
2802
+ (-equiv [o other] (identical? o other))
2803
+
2804
+ IDeref
2805
+ (-deref [_] state)
2806
+
2807
+ IMeta
2808
+ (-meta [_] meta)
2809
+
2810
+ IPrintable
2811
+ (-pr-seq [a opts]
2812
+ (concat ["#<Atom: "] (-pr-seq state opts) ">"))
2813
+
2814
+ IWatchable
2815
+ (-notify-watches [this oldval newval]
2816
+ (doseq [[key f] watches]
2817
+ (f key this oldval newval)))
2818
+ (-add-watch [this key f]
2819
+ (set! (.watches this) (assoc watches key f)))
2820
+ (-remove-watch [this key]
2821
+ (set! (.watches this) (dissoc watches key))))
2822
+
2823
+ (defn atom
2824
+ "Creates and returns an Atom with an initial value of x and zero or
2825
+ more options (in any order):
2826
+
2827
+ :meta metadata-map
2828
+
2829
+ :validator validate-fn
2830
+
2831
+ If metadata-map is supplied, it will be come the metadata on the
2832
+ atom. validate-fn must be nil or a side-effect-free fn of one
2833
+ argument, which will be passed the intended new state on any state
2834
+ change. If the new state is unacceptable, the validate-fn should
2835
+ return false or throw an Error. If either of these error conditions
2836
+ occur, then the value of the atom will not change."
2837
+ ([x] (Atom. x nil nil nil))
2838
+ ([x & {:keys [meta validator]}] (Atom. x meta validator nil)))
2839
+
2840
+ (defn reset!
2841
+ "Sets the value of atom to newval without regard for the
2842
+ current value. Returns newval."
2843
+ [a new-value]
2844
+ (when-let [validate (.validator a)]
2845
+ (assert (validate new-value) "Validator rejected reference state"))
2846
+ (let [old-value (.state a)]
2847
+ (set! (.state a) new-value)
2848
+ (-notify-watches a old-value new-value))
2849
+ new-value)
2850
+
2851
+ (defn swap!
2852
+ "Atomically swaps the value of atom to be:
2853
+ (apply f current-value-of-atom args). Note that f may be called
2854
+ multiple times, and thus should be free of side effects. Returns
2855
+ the value that was swapped in."
2856
+ ([a f]
2857
+ (reset! a (f (.state a))))
2858
+ ([a f x]
2859
+ (reset! a (f (.state a) x)))
2860
+ ([a f x y]
2861
+ (reset! a (f (.state a) x y)))
2862
+ ([a f x y z]
2863
+ (reset! a (f (.state a) x y z)))
2864
+ ([a f x y z & more]
2865
+ (reset! a (apply f (.state a) x y z more))))
2866
+
2867
+ (defn compare-and-set!
2868
+ "Atomically sets the value of atom to newval if and only if the
2869
+ current value of the atom is identical to oldval. Returns true if
2870
+ set happened, else false."
2871
+ [a oldval newval]
2872
+ (if (= a.state oldval)
2873
+ (do (reset! a newval) true)
2874
+ false))
2875
+
2876
+ ;; generic to all refs
2877
+ ;; (but currently hard-coded to atom!)
2878
+
2879
+ (defn deref
2880
+ [o]
2881
+ (-deref o))
2882
+
2883
+ (defn set-validator!
2884
+ "Sets the validator-fn for an atom. validator-fn must be nil or a
2885
+ side-effect-free fn of one argument, which will be passed the intended
2886
+ new state on any state change. If the new state is unacceptable, the
2887
+ validator-fn should return false or throw an Error. If the current state
2888
+ is not acceptable to the new validator, an Error will be thrown and the
2889
+ validator will not be changed."
2890
+ [iref val]
2891
+ (set! (.validator iref) val))
2892
+
2893
+ (defn get-validator
2894
+ "Gets the validator-fn for a var/ref/agent/atom."
2895
+ [iref]
2896
+ (.validator iref))
2897
+
2898
+ (defn alter-meta!
2899
+ "Atomically sets the metadata for a namespace/var/ref/agent/atom to be:
2900
+
2901
+ (apply f its-current-meta args)
2902
+
2903
+ f must be free of side-effects"
2904
+ [iref f & args]
2905
+ (set! (.meta iref) (apply f (.meta iref) args)))
2906
+
2907
+ (defn reset-meta!
2908
+ "Atomically resets the metadata for an atom"
2909
+ [iref m]
2910
+ (set! (.meta iref) m))
2911
+
2912
+ (defn add-watch
2913
+ "Alpha - subject to change.
2914
+
2915
+ Adds a watch function to an atom reference. The watch fn must be a
2916
+ fn of 4 args: a key, the reference, its old-state, its
2917
+ new-state. Whenever the reference's state might have been changed,
2918
+ any registered watches will have their functions called. The watch
2919
+ fn will be called synchronously. Note that an atom's state
2920
+ may have changed again prior to the fn call, so use old/new-state
2921
+ rather than derefing the reference. Keys must be unique per
2922
+ reference, and can be used to remove the watch with remove-watch,
2923
+ but are otherwise considered opaque by the watch mechanism. Bear in
2924
+ mind that regardless of the result or action of the watch fns the
2925
+ atom's value will change. Example:
2926
+
2927
+ (def a (atom 0))
2928
+ (add-watch a :inc (fn [k r o n] (assert (== 0 n))))
2929
+ (swap! a inc)
2930
+ ;; Assertion Error
2931
+ (deref a)
2932
+ ;=> 1"
2933
+ [iref key f]
2934
+ (-add-watch iref key f))
2935
+
2936
+ (defn remove-watch
2937
+ "Alpha - subject to change.
2938
+
2939
+ Removes a watch (set by add-watch) from a reference"
2940
+ [iref key]
2941
+ (-remove-watch iref key))
2942
+
2943
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; gensym ;;;;;;;;;;;;;;;;
2944
+ ;; Internal - do not use!
2945
+ (def gensym_counter nil)
2946
+
2947
+ (defn gensym
2948
+ "Returns a new symbol with a unique name. If a prefix string is
2949
+ supplied, the name is prefix# where # is some unique number. If
2950
+ prefix is not supplied, the prefix is 'G__'."
2951
+ ([] (gensym "G__"))
2952
+ ([prefix-string]
2953
+ (when (nil? gensym_counter)
2954
+ (set! gensym_counter (atom 0)))
2955
+ (symbol (str prefix-string (swap! gensym_counter inc)))))
2956
+
2957
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Fixtures ;;;;;;;;;;;;;;;;
2958
+
2959
+ (def fixture1 1)
2960
+ (def fixture2 2)
2961
+
2962
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Delay ;;;;;;;;;;;;;;;;;;;;
2963
+
2964
+ (deftype Delay [f state]
2965
+
2966
+ IDeref
2967
+ (-deref [_]
2968
+ (when-not @state
2969
+ (swap! state f))
2970
+ @state)
2971
+
2972
+ IPending
2973
+ (-realized? [d]
2974
+ (not (nil? @state))))
2975
+
2976
+ (defn delay
2977
+ "Takes a body of expressions and yields a Delay object that will
2978
+ invoke the body only the first time it is forced (with force or deref/@), and
2979
+ will cache the result and return it on all subsequent force
2980
+ calls."
2981
+ [& body]
2982
+ (Delay. (fn [] (apply identity body)) (atom nil)))
2983
+
2984
+ (defn delay?
2985
+ "returns true if x is a Delay created with delay"
2986
+ [x] (instance? cljs.core.Delay x))
2987
+
2988
+ (defn force
2989
+ "If x is a Delay, returns the (possibly cached) value of its expression, else returns x"
2990
+ [x]
2991
+ (if (delay? x)
2992
+ (deref x)
2993
+ x))
2994
+
2995
+ (defn realized?
2996
+ "Returns true if a value has been produced for a promise, delay, future or lazy sequence."
2997
+ [d]
2998
+ (-realized? d))
2999
+
3000
+ (defn js->clj
3001
+ "Recursively transforms JavaScript arrays into ClojureScript
3002
+ vectors, and JavaScript objects into ClojureScript maps. With
3003
+ option ':keywordize-keys true' will convert object fields from
3004
+ strings to keywords."
3005
+ [x & options]
3006
+ (let [{:keys [keywordize-keys]} options
3007
+ keyfn (if keywordize-keys keyword str)
3008
+ f (fn thisfn [x]
3009
+ (cond
3010
+ (seq? x) (doall (map thisfn x))
3011
+ (coll? x) (into (empty x) (map thisfn x))
3012
+ (goog.isArray x) (vec (map thisfn x))
3013
+ (goog.isObject x) (into {} (for [k (js-keys x)]
3014
+ [(keyfn k)
3015
+ (thisfn (aget x k))]))
3016
+ :else x))]
3017
+ (f x)))
3018
+
3019
+ (defn memoize
3020
+ "Returns a memoized version of a referentially transparent function. The
3021
+ memoized version of the function keeps a cache of the mapping from arguments
3022
+ to results and, when calls with the same arguments are repeated often, has
3023
+ higher performance at the expense of higher memory use."
3024
+ [f]
3025
+ (let [mem (atom {})]
3026
+ (fn [& args]
3027
+ (if-let [v (get @mem args)]
3028
+ v
3029
+ (let [ret (apply f args)]
3030
+ (swap! mem assoc args ret)
3031
+ ret)))))
3032
+
3033
+ (defn trampoline
3034
+ "trampoline can be used to convert algorithms requiring mutual
3035
+ recursion without stack consumption. Calls f with supplied args, if
3036
+ any. If f returns a fn, calls that fn with no arguments, and
3037
+ continues to repeat, until the return value is not a fn, then
3038
+ returns that non-fn value. Note that if you want to return a fn as a
3039
+ final value, you must wrap it in some data structure and unpack it
3040
+ after trampoline returns."
3041
+ ([f]
3042
+ (let [ret (f)]
3043
+ (if (fn? ret)
3044
+ (recur ret)
3045
+ ret)))
3046
+ ([f & args]
3047
+ (trampoline #(apply f args))))
3048
+
3049
+ (defn rand
3050
+ "Returns a random floating point number between 0 (inclusive) and
3051
+ n (default 1) (exclusive)."
3052
+ ([] (rand 1))
3053
+ ([n] (js* "Math.random() * ~{n}")))
3054
+
3055
+ (defn rand-int
3056
+ "Returns a random integer between 0 (inclusive) and n (exclusive)."
3057
+ [n] (js* "Math.floor(Math.random() * ~{n})"))
3058
+
3059
+ (defn rand-nth
3060
+ "Return a random element of the (sequential) collection. Will have
3061
+ the same performance characteristics as nth for the given
3062
+ collection."
3063
+ [coll]
3064
+ (nth coll (rand-int (count coll))))
3065
+
3066
+ (defn group-by
3067
+ "Returns a map of the elements of coll keyed by the result of
3068
+ f on each element. The value at each key will be a vector of the
3069
+ corresponding elements, in the order they appeared in coll."
3070
+ [f coll]
3071
+ (reduce
3072
+ (fn [ret x]
3073
+ (let [k (f x)]
3074
+ (assoc ret k (conj (get ret k []) x))))
3075
+ {} coll))
3076
+
3077
+ (defn make-hierarchy
3078
+ "Creates a hierarchy object for use with derive, isa? etc."
3079
+ [] {:parents {} :descendants {} :ancestors {}})
3080
+
3081
+ (def
3082
+ ^{:private true}
3083
+ global-hierarchy (atom (make-hierarchy)))
3084
+
3085
+ (defn isa?
3086
+ "Returns true if (= child parent), or child is directly or indirectly derived from
3087
+ parent, either via a Java type inheritance relationship or a
3088
+ relationship established via derive. h must be a hierarchy obtained
3089
+ from make-hierarchy, if not supplied defaults to the global
3090
+ hierarchy"
3091
+ ([child parent] (isa? @global-hierarchy child parent))
3092
+ ([h child parent]
3093
+ (or (= child parent)
3094
+ ;; (and (class? parent) (class? child)
3095
+ ;; (. ^Class parent isAssignableFrom child))
3096
+ (contains? ((:ancestors h) child) parent)
3097
+ ;;(and (class? child) (some #(contains? ((:ancestors h) %) parent) (supers child)))
3098
+ (and (vector? parent) (vector? child)
3099
+ (= (count parent) (count child))
3100
+ (loop [ret true i 0]
3101
+ (if (or (not ret) (= i (count parent)))
3102
+ ret
3103
+ (recur (isa? h (child i) (parent i)) (inc i))))))))
3104
+
3105
+ (defn parents
3106
+ "Returns the immediate parents of tag, either via a Java type
3107
+ inheritance relationship or a relationship established via derive. h
3108
+ must be a hierarchy obtained from make-hierarchy, if not supplied
3109
+ defaults to the global hierarchy"
3110
+ ([tag] (parents @global-hierarchy tag))
3111
+ ([h tag] (not-empty (get (:parents h) tag))))
3112
+
3113
+ (defn ancestors
3114
+ "Returns the immediate and indirect parents of tag, either via a Java type
3115
+ inheritance relationship or a relationship established via derive. h
3116
+ must be a hierarchy obtained from make-hierarchy, if not supplied
3117
+ defaults to the global hierarchy"
3118
+ ([tag] (ancestors @global-hierarchy tag))
3119
+ ([h tag] (not-empty (get (:ancestors h) tag))))
3120
+
3121
+ (defn descendants
3122
+ "Returns the immediate and indirect children of tag, through a
3123
+ relationship established via derive. h must be a hierarchy obtained
3124
+ from make-hierarchy, if not supplied defaults to the global
3125
+ hierarchy. Note: does not work on Java type inheritance
3126
+ relationships."
3127
+ ([tag] (descendants @global-hierarchy tag))
3128
+ ([h tag] (not-empty (get (:descendants h) tag))))
3129
+
3130
+ (defn derive
3131
+ "Establishes a parent/child relationship between parent and
3132
+ tag. Parent must be a namespace-qualified symbol or keyword and
3133
+ child can be either a namespace-qualified symbol or keyword or a
3134
+ class. h must be a hierarchy obtained from make-hierarchy, if not
3135
+ supplied defaults to, and modifies, the global hierarchy."
3136
+ ([tag parent]
3137
+ (assert (namespace parent))
3138
+ ;; (assert (or (class? tag) (and (instance? cljs.core.Named tag) (namespace tag))))
3139
+ (swap! global-hierarchy derive tag parent) nil)
3140
+ ([h tag parent]
3141
+ (assert (not= tag parent))
3142
+ ;; (assert (or (class? tag) (instance? clojure.lang.Named tag)))
3143
+ ;; (assert (instance? clojure.lang.INamed tag))
3144
+ ;; (assert (instance? clojure.lang.INamed parent))
3145
+ (let [tp (:parents h)
3146
+ td (:descendants h)
3147
+ ta (:ancestors h)
3148
+ tf (fn [m source sources target targets]
3149
+ (reduce (fn [ret k]
3150
+ (assoc ret k
3151
+ (reduce conj (get targets k #{}) (cons target (targets target)))))
3152
+ m (cons source (sources source))))]
3153
+ (or
3154
+ (when-not (contains? (tp tag) parent)
3155
+ (when (contains? (ta tag) parent)
3156
+ (throw (js/Error. (str tag "already has" parent "as ancestor"))))
3157
+ (when (contains? (ta parent) tag)
3158
+ (throw (js/Error. (str "Cyclic derivation:" parent "has" tag "as ancestor"))))
3159
+ {:parents (assoc (:parents h) tag (conj (get tp tag #{}) parent))
3160
+ :ancestors (tf (:ancestors h) tag td parent ta)
3161
+ :descendants (tf (:descendants h) parent ta tag td)})
3162
+ h))))
3163
+
3164
+ (defn underive
3165
+ "Removes a parent/child relationship between parent and
3166
+ tag. h must be a hierarchy obtained from make-hierarchy, if not
3167
+ supplied defaults to, and modifies, the global hierarchy."
3168
+ ([tag parent]
3169
+ ;; (alter-var-root #'global-hierarchy underive tag parent)
3170
+ (swap! global-hierarchy underive tag parent) nil)
3171
+ ([h tag parent]
3172
+ (let [parentMap (:parents h)
3173
+ childsParents (if (parentMap tag)
3174
+ (disj (parentMap tag) parent) #{})
3175
+ newParents (if (not-empty childsParents)
3176
+ (assoc parentMap tag childsParents)
3177
+ (dissoc parentMap tag))
3178
+ deriv-seq (flatten (map #(cons (first %) (interpose (first %) (second %)))
3179
+ (seq newParents)))]
3180
+ (if (contains? (parentMap tag) parent)
3181
+ (reduce #(apply derive %1 %2) (make-hierarchy)
3182
+ (partition 2 deriv-seq))
3183
+ h))))
3184
+
3185
+ (defn- reset-cache
3186
+ [method-cache method-table cached-hierarchy hierarchy]
3187
+ (swap! method-cache (fn [_] (deref method-table)))
3188
+ (swap! cached-hierarchy (fn [_] (deref hierarchy))))
3189
+
3190
+ (defn- prefers*
3191
+ [x y prefer-table]
3192
+ (let [xprefs (@prefer-table x)]
3193
+ (or
3194
+ (when (and xprefs (xprefs y))
3195
+ true)
3196
+ (loop [ps (parents y)]
3197
+ (when (pos? (count ps))
3198
+ (when (prefers* x (first ps) prefer-table)
3199
+ true)
3200
+ (recur (rest ps))))
3201
+ (loop [ps (parents x)]
3202
+ (when (pos? (count ps))
3203
+ (when (prefers* (first ps) y prefer-table)
3204
+ true)
3205
+ (recur (rest ps))))
3206
+ false)))
3207
+
3208
+ (defn- dominates
3209
+ [x y prefer-table]
3210
+ (or (prefers* x y prefer-table) (isa? x y)))
3211
+
3212
+ (defn- find-and-cache-best-method
3213
+ [name dispatch-val hierarchy method-table prefer-table method-cache cached-hierarchy]
3214
+ (let [best-entry (reduce (fn [be [k _ :as e]]
3215
+ (when (isa? dispatch-val k)
3216
+ (let [be2 (if (or (nil? be) (dominates k (first be) prefer-table))
3217
+ e
3218
+ be)]
3219
+ (when-not (dominates (first be2) k prefer-table)
3220
+ (throw (js/Error.
3221
+ (str "Multiple methods in multimethod '" name
3222
+ "' match dispatch value: " dispatch-val " -> " k
3223
+ " and " (first be2) ", and neither is preferred"))))
3224
+ be2)))
3225
+ nil @method-table)]
3226
+ (when best-entry
3227
+ (if (= @cached-hierarchy @hierarchy)
3228
+ (do
3229
+ (swap! method-cache assoc dispatch-val (second best-entry))
3230
+ (second best-entry))
3231
+ (do
3232
+ (reset-cache method-cache method-table cached-hierarchy hierarchy)
3233
+ (find-and-cache-best-method name dispatch-val hierarchy method-table prefer-table
3234
+ method-cache cached-hierarchy))))))
3235
+
3236
+ (defprotocol IMultiFn
3237
+ (-reset [mf])
3238
+ (-add-method [mf dispatch-val method])
3239
+ (-remove-method [mf dispatch-val])
3240
+ (-prefer-method [mf dispatch-val dispatch-val-y])
3241
+ (-get-method [mf dispatch-val])
3242
+ (-methods [mf])
3243
+ (-prefers [mf])
3244
+ (-invoke [mf args]))
3245
+
3246
+ (defn- do-invoke
3247
+ [mf dispatch-fn args]
3248
+ (let [dispatch-val (apply dispatch-fn args)
3249
+ target-fn (-get-method mf dispatch-val)]
3250
+ (when-not target-fn
3251
+ (throw (js/Error. (str "No method in multimethod '" name "' for dispatch value: " dispatch-val))))
3252
+ (apply target-fn args)))
3253
+
3254
+ (deftype MultiFn [name dispatch-fn default-dispatch-val hierarchy
3255
+ method-table prefer-table method-cache cached-hierarchy]
3256
+ IMultiFn
3257
+ (-reset [mf]
3258
+ (swap! method-table (fn [mf] {}))
3259
+ (swap! method-cache (fn [mf] {}))
3260
+ (swap! prefer-table (fn [mf] {}))
3261
+ (swap! cached-hierarchy (fn [mf] nil))
3262
+ mf)
3263
+
3264
+ (-add-method [mf dispatch-val method]
3265
+ (swap! method-table assoc dispatch-val method)
3266
+ (reset-cache method-cache method-table cached-hierarchy hierarchy)
3267
+ mf)
3268
+
3269
+ (-remove-method [mf dispatch-val]
3270
+ (swap! method-table dissoc dispatch-val)
3271
+ (reset-cache method-cache method-table cached-hierarchy hierarchy)
3272
+ mf)
3273
+
3274
+ (-get-method [mf dispatch-val]
3275
+ (when-not (= @cached-hierarchy @hierarchy)
3276
+ (reset-cache method-cache method-table cached-hierarchy hierarchy))
3277
+ (if-let [target-fn (@method-cache dispatch-val)]
3278
+ target-fn
3279
+ (if-let [target-fn (find-and-cache-best-method name dispatch-val hierarchy method-table
3280
+ prefer-table method-cache cached-hierarchy)]
3281
+ target-fn
3282
+ (@method-table default-dispatch-val))))
3283
+
3284
+ (-prefer-method [mf dispatch-val-x dispatch-val-y]
3285
+ (when (prefers* dispatch-val-x dispatch-val-y prefer-table)
3286
+ (throw (js/Error. (str "Preference conflict in multimethod '" name "': " dispatch-val-y
3287
+ " is already preferred to " dispatch-val-x))))
3288
+ (swap! prefer-table
3289
+ (fn [old]
3290
+ (assoc old dispatch-val-x
3291
+ (conj (get old dispatch-val-x #{})
3292
+ dispatch-val-y))))
3293
+ (reset-cache method-cache method-table cached-hierarchy hierarchy))
3294
+
3295
+ (-methods [mf] @method-table)
3296
+ (-prefers [mf] @prefer-table)
3297
+
3298
+ (-invoke [mf args] (do-invoke mf dispatch-fn args)))
3299
+
3300
+ (set! cljs.core.MultiFn.prototype.call
3301
+ (fn [_ & args] (-invoke (js* "this") args)))
3302
+
3303
+ (defn remove-all-methods
3304
+ "Removes all of the methods of multimethod."
3305
+ [multifn]
3306
+ (-reset multifn))
3307
+
3308
+ (defn remove-method
3309
+ "Removes the method of multimethod associated with dispatch-value."
3310
+ [multifn dispatch-val]
3311
+ (-remove-method multifn dispatch-val))
3312
+
3313
+ (defn prefer-method
3314
+ "Causes the multimethod to prefer matches of dispatch-val-x over dispatch-val-y
3315
+ when there is a conflict"
3316
+ [multifn dispatch-val-x dispatch-val-y]
3317
+ (-prefer-method multifn dispatch-val-x dispatch-val-y))
3318
+
3319
+ (defn methods
3320
+ "Given a multimethod, returns a map of dispatch values -> dispatch fns"
3321
+ [multifn] (-methods multifn))
3322
+
3323
+ (defn get-method
3324
+ "Given a multimethod and a dispatch value, returns the dispatch fn
3325
+ that would apply to that value, or nil if none apply and no default"
3326
+ [multifn dispatch-val] (-get-method multifn dispatch-val))
3327
+
3328
+ (defn prefers
3329
+ "Given a multimethod, returns a map of preferred value -> set of other values"
3330
+ [multifn] (-prefers multifn))