clementine 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +7 -0
- data/Gemfile +4 -0
- data/README.md +52 -0
- data/Rakefile +1 -0
- data/clementine.gemspec +23 -0
- data/lib/clementine.rb +27 -0
- data/lib/clementine/clementine_rails.rb +8 -0
- data/lib/clementine/clojurescript_engine.rb +49 -0
- data/lib/clementine/clojurescript_engine_mri.rb +65 -0
- data/lib/clementine/clojurescript_template.rb +21 -0
- data/lib/clementine/options.rb +9 -0
- data/lib/clementine/version.rb +3 -0
- data/test/clojurescript_engine_test.rb +46 -0
- data/test/options_test.rb +22 -0
- data/vendor/assets/bin/cljsc.clj +21 -0
- data/vendor/assets/lib/clojure.jar +0 -0
- data/vendor/assets/lib/compiler.jar +0 -0
- data/vendor/assets/lib/goog.jar +0 -0
- data/vendor/assets/lib/js.jar +0 -0
- data/vendor/assets/src/clj/cljs/closure.clj +823 -0
- data/vendor/assets/src/clj/cljs/compiler.clj +1341 -0
- data/vendor/assets/src/clj/cljs/core.clj +702 -0
- data/vendor/assets/src/clj/cljs/repl.clj +162 -0
- data/vendor/assets/src/clj/cljs/repl/browser.clj +341 -0
- data/vendor/assets/src/clj/cljs/repl/rhino.clj +170 -0
- data/vendor/assets/src/cljs/cljs/core.cljs +3330 -0
- data/vendor/assets/src/cljs/cljs/nodejs.cljs +11 -0
- data/vendor/assets/src/cljs/cljs/nodejs_externs.js +2 -0
- data/vendor/assets/src/cljs/cljs/nodejscli.cljs +9 -0
- data/vendor/assets/src/cljs/cljs/reader.cljs +360 -0
- data/vendor/assets/src/cljs/clojure/browser/dom.cljs +106 -0
- data/vendor/assets/src/cljs/clojure/browser/event.cljs +100 -0
- data/vendor/assets/src/cljs/clojure/browser/net.cljs +182 -0
- data/vendor/assets/src/cljs/clojure/browser/repl.cljs +109 -0
- data/vendor/assets/src/cljs/clojure/set.cljs +162 -0
- data/vendor/assets/src/cljs/clojure/string.cljs +160 -0
- data/vendor/assets/src/cljs/clojure/walk.cljs +94 -0
- data/vendor/assets/src/cljs/clojure/zip.cljs +291 -0
- 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))
|