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