clementine 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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))