annotate src/clojure/core.clj @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
rev   line source
rlm@10 1 ; Copyright (c) Rich Hickey. All rights reserved.
rlm@10 2 ; The use and distribution terms for this software are covered by the
rlm@10 3 ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
rlm@10 4 ; which can be found in the file epl-v10.html at the root of this distribution.
rlm@10 5 ; By using this software in any fashion, you are agreeing to be bound by
rlm@10 6 ; the terms of this license.
rlm@10 7 ; You must not remove this notice, or any other, from this software.
rlm@10 8
rlm@10 9 (ns clojure.core)
rlm@10 10
rlm@10 11 (def unquote)
rlm@10 12 (def unquote-splicing)
rlm@10 13
rlm@10 14 (def
rlm@10 15 ^{:arglists '([& items])
rlm@10 16 :doc "Creates a new list containing the items."
rlm@10 17 :added "1.0"}
rlm@10 18 list (. clojure.lang.PersistentList creator))
rlm@10 19
rlm@10 20 (def
rlm@10 21 ^{:arglists '([x seq])
rlm@10 22 :doc "Returns a new seq where x is the first element and seq is
rlm@10 23 the rest."
rlm@10 24 :added "1.0"}
rlm@10 25
rlm@10 26 cons (fn* cons [x seq] (. clojure.lang.RT (cons x seq))))
rlm@10 27
rlm@10 28 ;during bootstrap we don't have destructuring let, loop or fn, will redefine later
rlm@10 29 (def
rlm@10 30 ^{:macro true
rlm@10 31 :added "1.0"}
rlm@10 32 let (fn* let [&form &env & decl] (cons 'let* decl)))
rlm@10 33
rlm@10 34 (def
rlm@10 35 ^{:macro true
rlm@10 36 :added "1.0"}
rlm@10 37 loop (fn* loop [&form &env & decl] (cons 'loop* decl)))
rlm@10 38
rlm@10 39 (def
rlm@10 40 ^{:macro true
rlm@10 41 :added "1.0"}
rlm@10 42 fn (fn* fn [&form &env & decl]
rlm@10 43 (.withMeta ^clojure.lang.IObj (cons 'fn* decl)
rlm@10 44 (.meta ^clojure.lang.IMeta &form))))
rlm@10 45
rlm@10 46 (def
rlm@10 47 ^{:arglists '([coll])
rlm@10 48 :doc "Returns the first item in the collection. Calls seq on its
rlm@10 49 argument. If coll is nil, returns nil."
rlm@10 50 :added "1.0"}
rlm@10 51 first (fn first [coll] (. clojure.lang.RT (first coll))))
rlm@10 52
rlm@10 53 (def
rlm@10 54 ^{:arglists '([coll])
rlm@10 55 :tag clojure.lang.ISeq
rlm@10 56 :doc "Returns a seq of the items after the first. Calls seq on its
rlm@10 57 argument. If there are no more items, returns nil."
rlm@10 58 :added "1.0"}
rlm@10 59 next (fn next [x] (. clojure.lang.RT (next x))))
rlm@10 60
rlm@10 61 (def
rlm@10 62 ^{:arglists '([coll])
rlm@10 63 :tag clojure.lang.ISeq
rlm@10 64 :doc "Returns a possibly empty seq of the items after the first. Calls seq on its
rlm@10 65 argument."
rlm@10 66 :added "1.0"}
rlm@10 67 rest (fn rest [x] (. clojure.lang.RT (more x))))
rlm@10 68
rlm@10 69 (def
rlm@10 70 ^{:arglists '([coll x] [coll x & xs])
rlm@10 71 :doc "conj[oin]. Returns a new collection with the xs
rlm@10 72 'added'. (conj nil item) returns (item). The 'addition' may
rlm@10 73 happen at different 'places' depending on the concrete type."
rlm@10 74 :added "1.0"}
rlm@10 75 conj (fn conj
rlm@10 76 ([coll x] (. clojure.lang.RT (conj coll x)))
rlm@10 77 ([coll x & xs]
rlm@10 78 (if xs
rlm@10 79 (recur (conj coll x) (first xs) (next xs))
rlm@10 80 (conj coll x)))))
rlm@10 81
rlm@10 82 (def
rlm@10 83 ^{:doc "Same as (first (next x))"
rlm@10 84 :arglists '([x])
rlm@10 85 :added "1.0"}
rlm@10 86 second (fn second [x] (first (next x))))
rlm@10 87
rlm@10 88 (def
rlm@10 89 ^{:doc "Same as (first (first x))"
rlm@10 90 :arglists '([x])
rlm@10 91 :added "1.0"}
rlm@10 92 ffirst (fn ffirst [x] (first (first x))))
rlm@10 93
rlm@10 94 (def
rlm@10 95 ^{:doc "Same as (next (first x))"
rlm@10 96 :arglists '([x])
rlm@10 97 :added "1.0"}
rlm@10 98 nfirst (fn nfirst [x] (next (first x))))
rlm@10 99
rlm@10 100 (def
rlm@10 101 ^{:doc "Same as (first (next x))"
rlm@10 102 :arglists '([x])
rlm@10 103 :added "1.0"}
rlm@10 104 fnext (fn fnext [x] (first (next x))))
rlm@10 105
rlm@10 106 (def
rlm@10 107 ^{:doc "Same as (next (next x))"
rlm@10 108 :arglists '([x])
rlm@10 109 :added "1.0"}
rlm@10 110 nnext (fn nnext [x] (next (next x))))
rlm@10 111
rlm@10 112 (def
rlm@10 113 ^{:arglists '([coll])
rlm@10 114 :doc "Returns a seq on the collection. If the collection is
rlm@10 115 empty, returns nil. (seq nil) returns nil. seq also works on
rlm@10 116 Strings, native Java arrays (of reference types) and any objects
rlm@10 117 that implement Iterable."
rlm@10 118 :tag clojure.lang.ISeq
rlm@10 119 :added "1.0"}
rlm@10 120 seq (fn seq [coll] (. clojure.lang.RT (seq coll))))
rlm@10 121
rlm@10 122 (def
rlm@10 123 ^{:arglists '([^Class c x])
rlm@10 124 :doc "Evaluates x and tests if it is an instance of the class
rlm@10 125 c. Returns true or false"
rlm@10 126 :added "1.0"}
rlm@10 127 instance? (fn instance? [^Class c x] (. c (isInstance x))))
rlm@10 128
rlm@10 129 (def
rlm@10 130 ^{:arglists '([x])
rlm@10 131 :doc "Return true if x implements ISeq"
rlm@10 132 :added "1.0"}
rlm@10 133 seq? (fn seq? [x] (instance? clojure.lang.ISeq x)))
rlm@10 134
rlm@10 135 (def
rlm@10 136 ^{:arglists '([x])
rlm@10 137 :doc "Return true if x is a Character"
rlm@10 138 :added "1.0"}
rlm@10 139 char? (fn char? [x] (instance? Character x)))
rlm@10 140
rlm@10 141 (def
rlm@10 142 ^{:arglists '([x])
rlm@10 143 :doc "Return true if x is a String"
rlm@10 144 :added "1.0"}
rlm@10 145 string? (fn string? [x] (instance? String x)))
rlm@10 146
rlm@10 147 (def
rlm@10 148 ^{:arglists '([x])
rlm@10 149 :doc "Return true if x implements IPersistentMap"
rlm@10 150 :added "1.0"}
rlm@10 151 map? (fn map? [x] (instance? clojure.lang.IPersistentMap x)))
rlm@10 152
rlm@10 153 (def
rlm@10 154 ^{:arglists '([x])
rlm@10 155 :doc "Return true if x implements IPersistentVector"
rlm@10 156 :added "1.0"}
rlm@10 157 vector? (fn vector? [x] (instance? clojure.lang.IPersistentVector x)))
rlm@10 158
rlm@10 159 (def
rlm@10 160 ^{:arglists '([map key val] [map key val & kvs])
rlm@10 161 :doc "assoc[iate]. When applied to a map, returns a new map of the
rlm@10 162 same (hashed/sorted) type, that contains the mapping of key(s) to
rlm@10 163 val(s). When applied to a vector, returns a new vector that
rlm@10 164 contains val at index. Note - index must be <= (count vector)."
rlm@10 165 :added "1.0"}
rlm@10 166 assoc
rlm@10 167 (fn assoc
rlm@10 168 ([map key val] (. clojure.lang.RT (assoc map key val)))
rlm@10 169 ([map key val & kvs]
rlm@10 170 (let [ret (assoc map key val)]
rlm@10 171 (if kvs
rlm@10 172 (recur ret (first kvs) (second kvs) (nnext kvs))
rlm@10 173 ret)))))
rlm@10 174
rlm@10 175 ;;;;;;;;;;;;;;;;; metadata ;;;;;;;;;;;;;;;;;;;;;;;;;;;
rlm@10 176 (def
rlm@10 177 ^{:arglists '([obj])
rlm@10 178 :doc "Returns the metadata of obj, returns nil if there is no metadata."
rlm@10 179 :added "1.0"}
rlm@10 180 meta (fn meta [x]
rlm@10 181 (if (instance? clojure.lang.IMeta x)
rlm@10 182 (. ^clojure.lang.IMeta x (meta)))))
rlm@10 183
rlm@10 184 (def
rlm@10 185 ^{:arglists '([^clojure.lang.IObj obj m])
rlm@10 186 :doc "Returns an object of the same type and value as obj, with
rlm@10 187 map m as its metadata."
rlm@10 188 :added "1.0"}
rlm@10 189 with-meta (fn with-meta [^clojure.lang.IObj x m]
rlm@10 190 (. x (withMeta m))))
rlm@10 191
rlm@10 192 (def ^{:private true :dynamic true}
rlm@10 193 assert-valid-fdecl (fn [fdecl]))
rlm@10 194
rlm@10 195 (def
rlm@10 196 ^{:private true}
rlm@10 197 sigs
rlm@10 198 (fn [fdecl]
rlm@10 199 (assert-valid-fdecl fdecl)
rlm@10 200 (let [asig
rlm@10 201 (fn [fdecl]
rlm@10 202 (let [arglist (first fdecl)
rlm@10 203 ;elide implicit macro args
rlm@10 204 arglist (if (clojure.lang.Util/equals '&form (first arglist))
rlm@10 205 (clojure.lang.RT/subvec arglist 2 (clojure.lang.RT/count arglist))
rlm@10 206 arglist)
rlm@10 207 body (next fdecl)]
rlm@10 208 (if (map? (first body))
rlm@10 209 (if (next body)
rlm@10 210 (with-meta arglist (conj (if (meta arglist) (meta arglist) {}) (first body)))
rlm@10 211 arglist)
rlm@10 212 arglist)))]
rlm@10 213 (if (seq? (first fdecl))
rlm@10 214 (loop [ret [] fdecls fdecl]
rlm@10 215 (if fdecls
rlm@10 216 (recur (conj ret (asig (first fdecls))) (next fdecls))
rlm@10 217 (seq ret)))
rlm@10 218 (list (asig fdecl))))))
rlm@10 219
rlm@10 220
rlm@10 221 (def
rlm@10 222 ^{:arglists '([coll])
rlm@10 223 :doc "Return the last item in coll, in linear time"
rlm@10 224 :added "1.0"}
rlm@10 225 last (fn last [s]
rlm@10 226 (if (next s)
rlm@10 227 (recur (next s))
rlm@10 228 (first s))))
rlm@10 229
rlm@10 230 (def
rlm@10 231 ^{:arglists '([coll])
rlm@10 232 :doc "Return a seq of all but the last item in coll, in linear time"
rlm@10 233 :added "1.0"}
rlm@10 234 butlast (fn butlast [s]
rlm@10 235 (loop [ret [] s s]
rlm@10 236 (if (next s)
rlm@10 237 (recur (conj ret (first s)) (next s))
rlm@10 238 (seq ret)))))
rlm@10 239
rlm@10 240 (def
rlm@10 241
rlm@10 242 ^{:doc "Same as (def name (fn [params* ] exprs*)) or (def
rlm@10 243 name (fn ([params* ] exprs*)+)) with any doc-string or attrs added
rlm@10 244 to the var metadata"
rlm@10 245 :arglists '([name doc-string? attr-map? [params*] body]
rlm@10 246 [name doc-string? attr-map? ([params*] body)+ attr-map?])
rlm@10 247 :added "1.0"}
rlm@10 248 defn (fn defn [&form &env name & fdecl]
rlm@10 249 (let [m (if (string? (first fdecl))
rlm@10 250 {:doc (first fdecl)}
rlm@10 251 {})
rlm@10 252 fdecl (if (string? (first fdecl))
rlm@10 253 (next fdecl)
rlm@10 254 fdecl)
rlm@10 255 m (if (map? (first fdecl))
rlm@10 256 (conj m (first fdecl))
rlm@10 257 m)
rlm@10 258 fdecl (if (map? (first fdecl))
rlm@10 259 (next fdecl)
rlm@10 260 fdecl)
rlm@10 261 fdecl (if (vector? (first fdecl))
rlm@10 262 (list fdecl)
rlm@10 263 fdecl)
rlm@10 264 m (if (map? (last fdecl))
rlm@10 265 (conj m (last fdecl))
rlm@10 266 m)
rlm@10 267 fdecl (if (map? (last fdecl))
rlm@10 268 (butlast fdecl)
rlm@10 269 fdecl)
rlm@10 270 m (conj {:arglists (list 'quote (sigs fdecl))} m)
rlm@10 271 m (let [inline (:inline m)
rlm@10 272 ifn (first inline)
rlm@10 273 iname (second inline)]
rlm@10 274 ;; same as: (if (and (= 'fn ifn) (not (symbol? iname))) ...)
rlm@10 275 (if (if (clojure.lang.Util/equiv 'fn ifn)
rlm@10 276 (if (instance? clojure.lang.Symbol iname) false true))
rlm@10 277 ;; inserts the same fn name to the inline fn if it does not have one
rlm@10 278 (assoc m :inline (cons ifn (cons (clojure.lang.Symbol/intern (.concat (.getName name) "__inliner"))
rlm@10 279 (next inline))))
rlm@10 280 m))
rlm@10 281 m (conj (if (meta name) (meta name) {}) m)]
rlm@10 282 (list 'def (with-meta name m)
rlm@10 283 (list '.withMeta (cons `fn (cons name fdecl)) (list '.meta (list 'var name)))))))
rlm@10 284
rlm@10 285 (. (var defn) (setMacro))
rlm@10 286
rlm@10 287 (defn cast
rlm@10 288 "Throws a ClassCastException if x is not a c, else returns x."
rlm@10 289 {:added "1.0"}
rlm@10 290 [^Class c x]
rlm@10 291 (. c (cast x)))
rlm@10 292
rlm@10 293 (defn to-array
rlm@10 294 "Returns an array of Objects containing the contents of coll, which
rlm@10 295 can be any Collection. Maps to java.util.Collection.toArray()."
rlm@10 296 {:tag "[Ljava.lang.Object;"
rlm@10 297 :added "1.0"}
rlm@10 298 [coll] (. clojure.lang.RT (toArray coll)))
rlm@10 299
rlm@10 300 (defn vector
rlm@10 301 "Creates a new vector containing the args."
rlm@10 302 {:added "1.0"}
rlm@10 303 ([] [])
rlm@10 304 ([a] [a])
rlm@10 305 ([a b] [a b])
rlm@10 306 ([a b c] [a b c])
rlm@10 307 ([a b c d] [a b c d])
rlm@10 308 ([a b c d & args]
rlm@10 309 (. clojure.lang.LazilyPersistentVector (create (cons a (cons b (cons c (cons d args))))))))
rlm@10 310
rlm@10 311 (defn vec
rlm@10 312 "Creates a new vector containing the contents of coll."
rlm@10 313 {:added "1.0"}
rlm@10 314 ([coll]
rlm@10 315 (if (instance? java.util.Collection coll)
rlm@10 316 (clojure.lang.LazilyPersistentVector/create coll)
rlm@10 317 (. clojure.lang.LazilyPersistentVector (createOwning (to-array coll))))))
rlm@10 318
rlm@10 319 (defn hash-map
rlm@10 320 "keyval => key val
rlm@10 321 Returns a new hash map with supplied mappings."
rlm@10 322 {:added "1.0"}
rlm@10 323 ([] {})
rlm@10 324 ([& keyvals]
rlm@10 325 (. clojure.lang.PersistentHashMap (createWithCheck keyvals))))
rlm@10 326
rlm@10 327 (defn hash-set
rlm@10 328 "Returns a new hash set with supplied keys."
rlm@10 329 {:added "1.0"}
rlm@10 330 ([] #{})
rlm@10 331 ([& keys]
rlm@10 332 (clojure.lang.PersistentHashSet/createWithCheck keys)))
rlm@10 333
rlm@10 334 (defn sorted-map
rlm@10 335 "keyval => key val
rlm@10 336 Returns a new sorted map with supplied mappings."
rlm@10 337 {:added "1.0"}
rlm@10 338 ([& keyvals]
rlm@10 339 (clojure.lang.PersistentTreeMap/create keyvals)))
rlm@10 340
rlm@10 341 (defn sorted-map-by
rlm@10 342 "keyval => key val
rlm@10 343 Returns a new sorted map with supplied mappings, using the supplied comparator."
rlm@10 344 {:added "1.0"}
rlm@10 345 ([comparator & keyvals]
rlm@10 346 (clojure.lang.PersistentTreeMap/create comparator keyvals)))
rlm@10 347
rlm@10 348 (defn sorted-set
rlm@10 349 "Returns a new sorted set with supplied keys."
rlm@10 350 {:added "1.0"}
rlm@10 351 ([& keys]
rlm@10 352 (clojure.lang.PersistentTreeSet/create keys)))
rlm@10 353
rlm@10 354 (defn sorted-set-by
rlm@10 355 "Returns a new sorted set with supplied keys, using the supplied comparator."
rlm@10 356 {:added "1.1"}
rlm@10 357 ([comparator & keys]
rlm@10 358 (clojure.lang.PersistentTreeSet/create comparator keys)))
rlm@10 359
rlm@10 360
rlm@10 361 ;;;;;;;;;;;;;;;;;;;;
rlm@10 362 (defn nil?
rlm@10 363 "Returns true if x is nil, false otherwise."
rlm@10 364 {:tag Boolean
rlm@10 365 :added "1.0"}
rlm@10 366 [x] (clojure.lang.Util/identical x nil))
rlm@10 367
rlm@10 368 (def
rlm@10 369
rlm@10 370 ^{:doc "Like defn, but the resulting function name is declared as a
rlm@10 371 macro and will be used as a macro by the compiler when it is
rlm@10 372 called."
rlm@10 373 :arglists '([name doc-string? attr-map? [params*] body]
rlm@10 374 [name doc-string? attr-map? ([params*] body)+ attr-map?])
rlm@10 375 :added "1.0"}
rlm@10 376 defmacro (fn [&form &env
rlm@10 377 name & args]
rlm@10 378 (let [prefix (loop [p (list name) args args]
rlm@10 379 (let [f (first args)]
rlm@10 380 (if (string? f)
rlm@10 381 (recur (cons f p) (next args))
rlm@10 382 (if (map? f)
rlm@10 383 (recur (cons f p) (next args))
rlm@10 384 p))))
rlm@10 385 fdecl (loop [fd args]
rlm@10 386 (if (string? (first fd))
rlm@10 387 (recur (next fd))
rlm@10 388 (if (map? (first fd))
rlm@10 389 (recur (next fd))
rlm@10 390 fd)))
rlm@10 391 fdecl (if (vector? (first fdecl))
rlm@10 392 (list fdecl)
rlm@10 393 fdecl)
rlm@10 394 add-implicit-args (fn [fd]
rlm@10 395 (let [args (first fd)]
rlm@10 396 (cons (vec (cons '&form (cons '&env args))) (next fd))))
rlm@10 397 add-args (fn [acc ds]
rlm@10 398 (if (nil? ds)
rlm@10 399 acc
rlm@10 400 (let [d (first ds)]
rlm@10 401 (if (map? d)
rlm@10 402 (conj acc d)
rlm@10 403 (recur (conj acc (add-implicit-args d)) (next ds))))))
rlm@10 404 fdecl (seq (add-args [] fdecl))
rlm@10 405 decl (loop [p prefix d fdecl]
rlm@10 406 (if p
rlm@10 407 (recur (next p) (cons (first p) d))
rlm@10 408 d))]
rlm@10 409 (list 'do
rlm@10 410 (cons `defn decl)
rlm@10 411 (list '. (list 'var name) '(setMacro))
rlm@10 412 (list 'var name)))))
rlm@10 413
rlm@10 414
rlm@10 415 (. (var defmacro) (setMacro))
rlm@10 416
rlm@10 417 (defmacro when
rlm@10 418 "Evaluates test. If logical true, evaluates body in an implicit do."
rlm@10 419 {:added "1.0"}
rlm@10 420 [test & body]
rlm@10 421 (list 'if test (cons 'do body)))
rlm@10 422
rlm@10 423 (defmacro when-not
rlm@10 424 "Evaluates test. If logical false, evaluates body in an implicit do."
rlm@10 425 {:added "1.0"}
rlm@10 426 [test & body]
rlm@10 427 (list 'if test nil (cons 'do body)))
rlm@10 428
rlm@10 429 (defn false?
rlm@10 430 "Returns true if x is the value false, false otherwise."
rlm@10 431 {:tag Boolean,
rlm@10 432 :added "1.0"}
rlm@10 433 [x] (clojure.lang.Util/identical x false))
rlm@10 434
rlm@10 435 (defn true?
rlm@10 436 "Returns true if x is the value true, false otherwise."
rlm@10 437 {:tag Boolean,
rlm@10 438 :added "1.0"}
rlm@10 439 [x] (clojure.lang.Util/identical x true))
rlm@10 440
rlm@10 441 (defn not
rlm@10 442 "Returns true if x is logical false, false otherwise."
rlm@10 443 {:tag Boolean
rlm@10 444 :added "1.0"}
rlm@10 445 [x] (if x false true))
rlm@10 446
rlm@10 447 (defn str
rlm@10 448 "With no args, returns the empty string. With one arg x, returns
rlm@10 449 x.toString(). (str nil) returns the empty string. With more than
rlm@10 450 one arg, returns the concatenation of the str values of the args."
rlm@10 451 {:tag String
rlm@10 452 :added "1.0"}
rlm@10 453 ([] "")
rlm@10 454 ([^Object x]
rlm@10 455 (if (nil? x) "" (. x (toString))))
rlm@10 456 ([x & ys]
rlm@10 457 ((fn [^StringBuilder sb more]
rlm@10 458 (if more
rlm@10 459 (recur (. sb (append (str (first more)))) (next more))
rlm@10 460 (str sb)))
rlm@10 461 (new StringBuilder ^String (str x)) ys)))
rlm@10 462
rlm@10 463
rlm@10 464 (defn symbol?
rlm@10 465 "Return true if x is a Symbol"
rlm@10 466 {:added "1.0"}
rlm@10 467 [x] (instance? clojure.lang.Symbol x))
rlm@10 468
rlm@10 469 (defn keyword?
rlm@10 470 "Return true if x is a Keyword"
rlm@10 471 {:added "1.0"}
rlm@10 472 [x] (instance? clojure.lang.Keyword x))
rlm@10 473
rlm@10 474 (defn symbol
rlm@10 475 "Returns a Symbol with the given namespace and name."
rlm@10 476 {:tag clojure.lang.Symbol
rlm@10 477 :added "1.0"}
rlm@10 478 ([name] (if (symbol? name) name (clojure.lang.Symbol/intern name)))
rlm@10 479 ([ns name] (clojure.lang.Symbol/intern ns name)))
rlm@10 480
rlm@10 481 (defn gensym
rlm@10 482 "Returns a new symbol with a unique name. If a prefix string is
rlm@10 483 supplied, the name is prefix# where # is some unique number. If
rlm@10 484 prefix is not supplied, the prefix is 'G__'."
rlm@10 485 {:added "1.0"}
rlm@10 486 ([] (gensym "G__"))
rlm@10 487 ([prefix-string] (. clojure.lang.Symbol (intern (str prefix-string (str (. clojure.lang.RT (nextID))))))))
rlm@10 488
rlm@10 489 (defmacro cond
rlm@10 490 "Takes a set of test/expr pairs. It evaluates each test one at a
rlm@10 491 time. If a test returns logical true, cond evaluates and returns
rlm@10 492 the value of the corresponding expr and doesn't evaluate any of the
rlm@10 493 other tests or exprs. (cond) returns nil."
rlm@10 494 {:added "1.0"}
rlm@10 495 [& clauses]
rlm@10 496 (when clauses
rlm@10 497 (list 'if (first clauses)
rlm@10 498 (if (next clauses)
rlm@10 499 (second clauses)
rlm@10 500 (throw (IllegalArgumentException.
rlm@10 501 "cond requires an even number of forms")))
rlm@10 502 (cons 'clojure.core/cond (next (next clauses))))))
rlm@10 503
rlm@10 504 (defn keyword
rlm@10 505 "Returns a Keyword with the given namespace and name. Do not use :
rlm@10 506 in the keyword strings, it will be added automatically."
rlm@10 507 {:tag clojure.lang.Keyword
rlm@10 508 :added "1.0"}
rlm@10 509 ([name] (cond (keyword? name) name
rlm@10 510 (symbol? name) (clojure.lang.Keyword/intern ^clojure.lang.Symbol name)
rlm@10 511 (string? name) (clojure.lang.Keyword/intern ^String name)))
rlm@10 512 ([ns name] (clojure.lang.Keyword/intern ns name)))
rlm@10 513
rlm@10 514 (defn spread
rlm@10 515 {:private true}
rlm@10 516 [arglist]
rlm@10 517 (cond
rlm@10 518 (nil? arglist) nil
rlm@10 519 (nil? (next arglist)) (seq (first arglist))
rlm@10 520 :else (cons (first arglist) (spread (next arglist)))))
rlm@10 521
rlm@10 522 (defn list*
rlm@10 523 "Creates a new list containing the items prepended to the rest, the
rlm@10 524 last of which will be treated as a sequence."
rlm@10 525 {:added "1.0"}
rlm@10 526 ([args] (seq args))
rlm@10 527 ([a args] (cons a args))
rlm@10 528 ([a b args] (cons a (cons b args)))
rlm@10 529 ([a b c args] (cons a (cons b (cons c args))))
rlm@10 530 ([a b c d & more]
rlm@10 531 (cons a (cons b (cons c (cons d (spread more)))))))
rlm@10 532
rlm@10 533 (defn apply
rlm@10 534 "Applies fn f to the argument list formed by prepending args to argseq."
rlm@10 535 {:arglists '([f args* argseq])
rlm@10 536 :added "1.0"}
rlm@10 537 ([^clojure.lang.IFn f args]
rlm@10 538 (. f (applyTo (seq args))))
rlm@10 539 ([^clojure.lang.IFn f x args]
rlm@10 540 (. f (applyTo (list* x args))))
rlm@10 541 ([^clojure.lang.IFn f x y args]
rlm@10 542 (. f (applyTo (list* x y args))))
rlm@10 543 ([^clojure.lang.IFn f x y z args]
rlm@10 544 (. f (applyTo (list* x y z args))))
rlm@10 545 ([^clojure.lang.IFn f a b c d & args]
rlm@10 546 (. f (applyTo (cons a (cons b (cons c (cons d (spread args)))))))))
rlm@10 547
rlm@10 548 (defn vary-meta
rlm@10 549 "Returns an object of the same type and value as obj, with
rlm@10 550 (apply f (meta obj) args) as its metadata."
rlm@10 551 {:added "1.0"}
rlm@10 552 [obj f & args]
rlm@10 553 (with-meta obj (apply f (meta obj) args)))
rlm@10 554
rlm@10 555 (defmacro lazy-seq
rlm@10 556 "Takes a body of expressions that returns an ISeq or nil, and yields
rlm@10 557 a Seqable object that will invoke the body only the first time seq
rlm@10 558 is called, and will cache the result and return it on all subsequent
rlm@10 559 seq calls."
rlm@10 560 {:added "1.0"}
rlm@10 561 [& body]
rlm@10 562 (list 'new 'clojure.lang.LazySeq (list* '^{:once true} fn* [] body)))
rlm@10 563
rlm@10 564 (defn ^clojure.lang.ChunkBuffer chunk-buffer [capacity]
rlm@10 565 (clojure.lang.ChunkBuffer. capacity))
rlm@10 566
rlm@10 567 (defn chunk-append [^clojure.lang.ChunkBuffer b x]
rlm@10 568 (.add b x))
rlm@10 569
rlm@10 570 (defn chunk [^clojure.lang.ChunkBuffer b]
rlm@10 571 (.chunk b))
rlm@10 572
rlm@10 573 (defn ^clojure.lang.IChunk chunk-first [^clojure.lang.IChunkedSeq s]
rlm@10 574 (.chunkedFirst s))
rlm@10 575
rlm@10 576 (defn ^clojure.lang.ISeq chunk-rest [^clojure.lang.IChunkedSeq s]
rlm@10 577 (.chunkedMore s))
rlm@10 578
rlm@10 579 (defn ^clojure.lang.ISeq chunk-next [^clojure.lang.IChunkedSeq s]
rlm@10 580 (.chunkedNext s))
rlm@10 581
rlm@10 582 (defn chunk-cons [chunk rest]
rlm@10 583 (if (clojure.lang.Numbers/isZero (clojure.lang.RT/count chunk))
rlm@10 584 rest
rlm@10 585 (clojure.lang.ChunkedCons. chunk rest)))
rlm@10 586
rlm@10 587 (defn chunked-seq? [s]
rlm@10 588 (instance? clojure.lang.IChunkedSeq s))
rlm@10 589
rlm@10 590 (defn concat
rlm@10 591 "Returns a lazy seq representing the concatenation of the elements in the supplied colls."
rlm@10 592 {:added "1.0"}
rlm@10 593 ([] (lazy-seq nil))
rlm@10 594 ([x] (lazy-seq x))
rlm@10 595 ([x y]
rlm@10 596 (lazy-seq
rlm@10 597 (let [s (seq x)]
rlm@10 598 (if s
rlm@10 599 (if (chunked-seq? s)
rlm@10 600 (chunk-cons (chunk-first s) (concat (chunk-rest s) y))
rlm@10 601 (cons (first s) (concat (rest s) y)))
rlm@10 602 y))))
rlm@10 603 ([x y & zs]
rlm@10 604 (let [cat (fn cat [xys zs]
rlm@10 605 (lazy-seq
rlm@10 606 (let [xys (seq xys)]
rlm@10 607 (if xys
rlm@10 608 (if (chunked-seq? xys)
rlm@10 609 (chunk-cons (chunk-first xys)
rlm@10 610 (cat (chunk-rest xys) zs))
rlm@10 611 (cons (first xys) (cat (rest xys) zs)))
rlm@10 612 (when zs
rlm@10 613 (cat (first zs) (next zs)))))))]
rlm@10 614 (cat (concat x y) zs))))
rlm@10 615
rlm@10 616 ;;;;;;;;;;;;;;;;at this point all the support for syntax-quote exists;;;;;;;;;;;;;;;;;;;;;;
rlm@10 617 (defmacro delay
rlm@10 618 "Takes a body of expressions and yields a Delay object that will
rlm@10 619 invoke the body only the first time it is forced (with force or deref/@), and
rlm@10 620 will cache the result and return it on all subsequent force
rlm@10 621 calls."
rlm@10 622 {:added "1.0"}
rlm@10 623 [& body]
rlm@10 624 (list 'new 'clojure.lang.Delay (list* `^{:once true} fn* [] body)))
rlm@10 625
rlm@10 626 (defn delay?
rlm@10 627 "returns true if x is a Delay created with delay"
rlm@10 628 {:added "1.0"}
rlm@10 629 [x] (instance? clojure.lang.Delay x))
rlm@10 630
rlm@10 631 (defn force
rlm@10 632 "If x is a Delay, returns the (possibly cached) value of its expression, else returns x"
rlm@10 633 {:added "1.0"}
rlm@10 634 [x] (. clojure.lang.Delay (force x)))
rlm@10 635
rlm@10 636 (defmacro if-not
rlm@10 637 "Evaluates test. If logical false, evaluates and returns then expr,
rlm@10 638 otherwise else expr, if supplied, else nil."
rlm@10 639 {:added "1.0"}
rlm@10 640 ([test then] `(if-not ~test ~then nil))
rlm@10 641 ([test then else]
rlm@10 642 `(if (not ~test) ~then ~else)))
rlm@10 643
rlm@10 644 (defn identical?
rlm@10 645 "Tests if 2 arguments are the same object"
rlm@10 646 {:inline (fn [x y] `(. clojure.lang.Util identical ~x ~y))
rlm@10 647 :inline-arities #{2}
rlm@10 648 :added "1.0"}
rlm@10 649 ([x y] (clojure.lang.Util/identical x y)))
rlm@10 650
rlm@10 651 (defn =
rlm@10 652 "Equality. Returns true if x equals y, false if not. Same as
rlm@10 653 Java x.equals(y) except it also works for nil, and compares
rlm@10 654 numbers and collections in a type-independent manner. Clojure's immutable data
rlm@10 655 structures define equals() (and thus =) as a value, not an identity,
rlm@10 656 comparison."
rlm@10 657 {:inline (fn [x y] `(. clojure.lang.Util equiv ~x ~y))
rlm@10 658 :inline-arities #{2}
rlm@10 659 :added "1.0"}
rlm@10 660 ([x] true)
rlm@10 661 ([x y] (clojure.lang.Util/equiv x y))
rlm@10 662 ([x y & more]
rlm@10 663 (if (= x y)
rlm@10 664 (if (next more)
rlm@10 665 (recur y (first more) (next more))
rlm@10 666 (= y (first more)))
rlm@10 667 false)))
rlm@10 668
rlm@10 669 (defn not=
rlm@10 670 "Same as (not (= obj1 obj2))"
rlm@10 671 {:tag Boolean
rlm@10 672 :added "1.0"}
rlm@10 673 ([x] false)
rlm@10 674 ([x y] (not (= x y)))
rlm@10 675 ([x y & more]
rlm@10 676 (not (apply = x y more))))
rlm@10 677
rlm@10 678
rlm@10 679
rlm@10 680 (defn compare
rlm@10 681 "Comparator. Returns a negative number, zero, or a positive number
rlm@10 682 when x is logically 'less than', 'equal to', or 'greater than'
rlm@10 683 y. Same as Java x.compareTo(y) except it also works for nil, and
rlm@10 684 compares numbers and collections in a type-independent manner. x
rlm@10 685 must implement Comparable"
rlm@10 686 {
rlm@10 687 :inline (fn [x y] `(. clojure.lang.Util compare ~x ~y))
rlm@10 688 :added "1.0"}
rlm@10 689 [x y] (. clojure.lang.Util (compare x y)))
rlm@10 690
rlm@10 691 (defmacro and
rlm@10 692 "Evaluates exprs one at a time, from left to right. If a form
rlm@10 693 returns logical false (nil or false), and returns that value and
rlm@10 694 doesn't evaluate any of the other expressions, otherwise it returns
rlm@10 695 the value of the last expr. (and) returns true."
rlm@10 696 {:added "1.0"}
rlm@10 697 ([] true)
rlm@10 698 ([x] x)
rlm@10 699 ([x & next]
rlm@10 700 `(let [and# ~x]
rlm@10 701 (if and# (and ~@next) and#))))
rlm@10 702
rlm@10 703 (defmacro or
rlm@10 704 "Evaluates exprs one at a time, from left to right. If a form
rlm@10 705 returns a logical true value, or returns that value and doesn't
rlm@10 706 evaluate any of the other expressions, otherwise it returns the
rlm@10 707 value of the last expression. (or) returns nil."
rlm@10 708 {:added "1.0"}
rlm@10 709 ([] nil)
rlm@10 710 ([x] x)
rlm@10 711 ([x & next]
rlm@10 712 `(let [or# ~x]
rlm@10 713 (if or# or# (or ~@next)))))
rlm@10 714
rlm@10 715 ;;;;;;;;;;;;;;;;;;; sequence fns ;;;;;;;;;;;;;;;;;;;;;;;
rlm@10 716 (defn zero?
rlm@10 717 "Returns true if num is zero, else false"
rlm@10 718 {
rlm@10 719 :inline (fn [x] `(. clojure.lang.Numbers (isZero ~x)))
rlm@10 720 :added "1.0"}
rlm@10 721 [x] (. clojure.lang.Numbers (isZero x)))
rlm@10 722
rlm@10 723 (defn count
rlm@10 724 "Returns the number of items in the collection. (count nil) returns
rlm@10 725 0. Also works on strings, arrays, and Java Collections and Maps"
rlm@10 726 {
rlm@10 727 :inline (fn [x] `(. clojure.lang.RT (count ~x)))
rlm@10 728 :added "1.0"}
rlm@10 729 [coll] (clojure.lang.RT/count coll))
rlm@10 730
rlm@10 731 (defn int
rlm@10 732 "Coerce to int"
rlm@10 733 {
rlm@10 734 :inline (fn [x] `(. clojure.lang.RT (intCast ~x)))
rlm@10 735 :added "1.0"}
rlm@10 736 [x] (. clojure.lang.RT (intCast x)))
rlm@10 737
rlm@10 738 (defn nth
rlm@10 739 "Returns the value at the index. get returns nil if index out of
rlm@10 740 bounds, nth throws an exception unless not-found is supplied. nth
rlm@10 741 also works for strings, Java arrays, regex Matchers and Lists, and,
rlm@10 742 in O(n) time, for sequences."
rlm@10 743 {:inline (fn [c i & nf] `(. clojure.lang.RT (nth ~c ~i ~@nf)))
rlm@10 744 :inline-arities #{2 3}
rlm@10 745 :added "1.0"}
rlm@10 746 ([coll index] (. clojure.lang.RT (nth coll index)))
rlm@10 747 ([coll index not-found] (. clojure.lang.RT (nth coll index not-found))))
rlm@10 748
rlm@10 749 (defn <
rlm@10 750 "Returns non-nil if nums are in monotonically increasing order,
rlm@10 751 otherwise false."
rlm@10 752 {:inline (fn [x y] `(. clojure.lang.Numbers (lt ~x ~y)))
rlm@10 753 :inline-arities #{2}
rlm@10 754 :added "1.0"}
rlm@10 755 ([x] true)
rlm@10 756 ([x y] (. clojure.lang.Numbers (lt x y)))
rlm@10 757 ([x y & more]
rlm@10 758 (if (< x y)
rlm@10 759 (if (next more)
rlm@10 760 (recur y (first more) (next more))
rlm@10 761 (< y (first more)))
rlm@10 762 false)))
rlm@10 763
rlm@10 764 (defn inc
rlm@10 765 "Returns a number one greater than num."
rlm@10 766 {:inline (fn [x] `(. clojure.lang.Numbers (inc ~x)))
rlm@10 767 :added "1.0"}
rlm@10 768 [x] (. clojure.lang.Numbers (inc x)))
rlm@10 769
rlm@10 770 ;; reduce is defined again later after InternalReduce loads
rlm@10 771 (def
rlm@10 772 ^{:arglists '([f coll] [f val coll])
rlm@10 773 :doc "f should be a function of 2 arguments. If val is not supplied,
rlm@10 774 returns the result of applying f to the first 2 items in coll, then
rlm@10 775 applying f to that result and the 3rd item, etc. If coll contains no
rlm@10 776 items, f must accept no arguments as well, and reduce returns the
rlm@10 777 result of calling f with no arguments. If coll has only 1 item, it
rlm@10 778 is returned and f is not called. If val is supplied, returns the
rlm@10 779 result of applying f to val and the first item in coll, then
rlm@10 780 applying f to that result and the 2nd item, etc. If coll contains no
rlm@10 781 items, returns val and f is not called."
rlm@10 782 :added "1.0"}
rlm@10 783 reduce
rlm@10 784 (fn r
rlm@10 785 ([f coll]
rlm@10 786 (let [s (seq coll)]
rlm@10 787 (if s
rlm@10 788 (r f (first s) (next s))
rlm@10 789 (f))))
rlm@10 790 ([f val coll]
rlm@10 791 (let [s (seq coll)]
rlm@10 792 (if s
rlm@10 793 (if (chunked-seq? s)
rlm@10 794 (recur f
rlm@10 795 (.reduce (chunk-first s) f val)
rlm@10 796 (chunk-next s))
rlm@10 797 (recur f (f val (first s)) (next s)))
rlm@10 798 val)))))
rlm@10 799
rlm@10 800 (defn reverse
rlm@10 801 "Returns a seq of the items in coll in reverse order. Not lazy."
rlm@10 802 {:added "1.0"}
rlm@10 803 [coll]
rlm@10 804 (reduce conj () coll))
rlm@10 805
rlm@10 806 ;;math stuff
rlm@10 807 (defn +
rlm@10 808 "Returns the sum of nums. (+) returns 0."
rlm@10 809 {:inline (fn [x y] `(. clojure.lang.Numbers (add ~x ~y)))
rlm@10 810 :inline-arities #{2}
rlm@10 811 :added "1.0"}
rlm@10 812 ([] 0)
rlm@10 813 ([x] (cast Number x))
rlm@10 814 ([x y] (. clojure.lang.Numbers (add x y)))
rlm@10 815 ([x y & more]
rlm@10 816 (reduce + (+ x y) more)))
rlm@10 817
rlm@10 818 (defn *
rlm@10 819 "Returns the product of nums. (*) returns 1."
rlm@10 820 {:inline (fn [x y] `(. clojure.lang.Numbers (multiply ~x ~y)))
rlm@10 821 :inline-arities #{2}
rlm@10 822 :added "1.0"}
rlm@10 823 ([] 1)
rlm@10 824 ([x] (cast Number x))
rlm@10 825 ([x y] (. clojure.lang.Numbers (multiply x y)))
rlm@10 826 ([x y & more]
rlm@10 827 (reduce * (* x y) more)))
rlm@10 828
rlm@10 829 (defn /
rlm@10 830 "If no denominators are supplied, returns 1/numerator,
rlm@10 831 else returns numerator divided by all of the denominators."
rlm@10 832 {:inline (fn [x y] `(. clojure.lang.Numbers (divide ~x ~y)))
rlm@10 833 :inline-arities #{2}
rlm@10 834 :added "1.0"}
rlm@10 835 ([x] (/ 1 x))
rlm@10 836 ([x y] (. clojure.lang.Numbers (divide x y)))
rlm@10 837 ([x y & more]
rlm@10 838 (reduce / (/ x y) more)))
rlm@10 839
rlm@10 840 (defn -
rlm@10 841 "If no ys are supplied, returns the negation of x, else subtracts
rlm@10 842 the ys from x and returns the result."
rlm@10 843 {:inline (fn [& args] `(. clojure.lang.Numbers (minus ~@args)))
rlm@10 844 :inline-arities #{1 2}
rlm@10 845 :added "1.0"}
rlm@10 846 ([x] (. clojure.lang.Numbers (minus x)))
rlm@10 847 ([x y] (. clojure.lang.Numbers (minus x y)))
rlm@10 848 ([x y & more]
rlm@10 849 (reduce - (- x y) more)))
rlm@10 850
rlm@10 851 (defn <=
rlm@10 852 "Returns non-nil if nums are in monotonically non-decreasing order,
rlm@10 853 otherwise false."
rlm@10 854 {:inline (fn [x y] `(. clojure.lang.Numbers (lte ~x ~y)))
rlm@10 855 :inline-arities #{2}
rlm@10 856 :added "1.0"}
rlm@10 857 ([x] true)
rlm@10 858 ([x y] (. clojure.lang.Numbers (lte x y)))
rlm@10 859 ([x y & more]
rlm@10 860 (if (<= x y)
rlm@10 861 (if (next more)
rlm@10 862 (recur y (first more) (next more))
rlm@10 863 (<= y (first more)))
rlm@10 864 false)))
rlm@10 865
rlm@10 866 (defn >
rlm@10 867 "Returns non-nil if nums are in monotonically decreasing order,
rlm@10 868 otherwise false."
rlm@10 869 {:inline (fn [x y] `(. clojure.lang.Numbers (gt ~x ~y)))
rlm@10 870 :inline-arities #{2}
rlm@10 871 :added "1.0"}
rlm@10 872 ([x] true)
rlm@10 873 ([x y] (. clojure.lang.Numbers (gt x y)))
rlm@10 874 ([x y & more]
rlm@10 875 (if (> x y)
rlm@10 876 (if (next more)
rlm@10 877 (recur y (first more) (next more))
rlm@10 878 (> y (first more)))
rlm@10 879 false)))
rlm@10 880
rlm@10 881 (defn >=
rlm@10 882 "Returns non-nil if nums are in monotonically non-increasing order,
rlm@10 883 otherwise false."
rlm@10 884 {:inline (fn [x y] `(. clojure.lang.Numbers (gte ~x ~y)))
rlm@10 885 :inline-arities #{2}
rlm@10 886 :added "1.0"}
rlm@10 887 ([x] true)
rlm@10 888 ([x y] (. clojure.lang.Numbers (gte x y)))
rlm@10 889 ([x y & more]
rlm@10 890 (if (>= x y)
rlm@10 891 (if (next more)
rlm@10 892 (recur y (first more) (next more))
rlm@10 893 (>= y (first more)))
rlm@10 894 false)))
rlm@10 895
rlm@10 896 (defn ==
rlm@10 897 "Returns non-nil if nums all have the same value, otherwise false"
rlm@10 898 {:inline (fn [x y] `(. clojure.lang.Numbers (equiv ~x ~y)))
rlm@10 899 :inline-arities #{2}
rlm@10 900 :added "1.0"}
rlm@10 901 ([x] true)
rlm@10 902 ([x y] (. clojure.lang.Numbers (equiv x y)))
rlm@10 903 ([x y & more]
rlm@10 904 (if (== x y)
rlm@10 905 (if (next more)
rlm@10 906 (recur y (first more) (next more))
rlm@10 907 (== y (first more)))
rlm@10 908 false)))
rlm@10 909
rlm@10 910 (defn max
rlm@10 911 "Returns the greatest of the nums."
rlm@10 912 {:added "1.0"}
rlm@10 913 ([x] x)
rlm@10 914 ([x y] (if (> x y) x y))
rlm@10 915 ([x y & more]
rlm@10 916 (reduce max (max x y) more)))
rlm@10 917
rlm@10 918 (defn min
rlm@10 919 "Returns the least of the nums."
rlm@10 920 {:added "1.0"}
rlm@10 921 ([x] x)
rlm@10 922 ([x y] (if (< x y) x y))
rlm@10 923 ([x y & more]
rlm@10 924 (reduce min (min x y) more)))
rlm@10 925
rlm@10 926 (defn dec
rlm@10 927 "Returns a number one less than num."
rlm@10 928 {:inline (fn [x] `(. clojure.lang.Numbers (dec ~x)))
rlm@10 929 :added "1.0"}
rlm@10 930 [x] (. clojure.lang.Numbers (dec x)))
rlm@10 931
rlm@10 932 (defn unchecked-inc
rlm@10 933 "Returns a number one greater than x, an int or long.
rlm@10 934 Note - uses a primitive operator subject to overflow."
rlm@10 935 {:inline (fn [x] `(. clojure.lang.Numbers (unchecked_inc ~x)))
rlm@10 936 :added "1.0"}
rlm@10 937 [x] (. clojure.lang.Numbers (unchecked_inc x)))
rlm@10 938
rlm@10 939 (defn unchecked-dec
rlm@10 940 "Returns a number one less than x, an int or long.
rlm@10 941 Note - uses a primitive operator subject to overflow."
rlm@10 942 {:inline (fn [x] `(. clojure.lang.Numbers (unchecked_dec ~x)))
rlm@10 943 :added "1.0"}
rlm@10 944 [x] (. clojure.lang.Numbers (unchecked_dec x)))
rlm@10 945
rlm@10 946 (defn unchecked-negate
rlm@10 947 "Returns the negation of x, an int or long.
rlm@10 948 Note - uses a primitive operator subject to overflow."
rlm@10 949 {:inline (fn [x] `(. clojure.lang.Numbers (unchecked_negate ~x)))
rlm@10 950 :added "1.0"}
rlm@10 951 [x] (. clojure.lang.Numbers (unchecked_negate x)))
rlm@10 952
rlm@10 953 (defn unchecked-add
rlm@10 954 "Returns the sum of x and y, both int or long.
rlm@10 955 Note - uses a primitive operator subject to overflow."
rlm@10 956 {:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_add ~x ~y)))
rlm@10 957 :added "1.0"}
rlm@10 958 [x y] (. clojure.lang.Numbers (unchecked_add x y)))
rlm@10 959
rlm@10 960 (defn unchecked-subtract
rlm@10 961 "Returns the difference of x and y, both int or long.
rlm@10 962 Note - uses a primitive operator subject to overflow."
rlm@10 963 {:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_subtract ~x ~y)))
rlm@10 964 :added "1.0"}
rlm@10 965 [x y] (. clojure.lang.Numbers (unchecked_subtract x y)))
rlm@10 966
rlm@10 967 (defn unchecked-multiply
rlm@10 968 "Returns the product of x and y, both int or long.
rlm@10 969 Note - uses a primitive operator subject to overflow."
rlm@10 970 {:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_multiply ~x ~y)))
rlm@10 971 :added "1.0"}
rlm@10 972 [x y] (. clojure.lang.Numbers (unchecked_multiply x y)))
rlm@10 973
rlm@10 974 (defn unchecked-divide
rlm@10 975 "Returns the division of x by y, both int or long.
rlm@10 976 Note - uses a primitive operator subject to truncation."
rlm@10 977 {:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_divide ~x ~y)))
rlm@10 978 :added "1.0"}
rlm@10 979 [x y] (. clojure.lang.Numbers (unchecked_divide x y)))
rlm@10 980
rlm@10 981 (defn unchecked-remainder
rlm@10 982 "Returns the remainder of division of x by y, both int or long.
rlm@10 983 Note - uses a primitive operator subject to truncation."
rlm@10 984 {:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_remainder ~x ~y)))
rlm@10 985 :added "1.0"}
rlm@10 986 [x y] (. clojure.lang.Numbers (unchecked_remainder x y)))
rlm@10 987
rlm@10 988 (defn pos?
rlm@10 989 "Returns true if num is greater than zero, else false"
rlm@10 990 {
rlm@10 991 :inline (fn [x] `(. clojure.lang.Numbers (isPos ~x)))
rlm@10 992 :added "1.0"}
rlm@10 993 [x] (. clojure.lang.Numbers (isPos x)))
rlm@10 994
rlm@10 995 (defn neg?
rlm@10 996 "Returns true if num is less than zero, else false"
rlm@10 997 {
rlm@10 998 :inline (fn [x] `(. clojure.lang.Numbers (isNeg ~x)))
rlm@10 999 :added "1.0"}
rlm@10 1000 [x] (. clojure.lang.Numbers (isNeg x)))
rlm@10 1001
rlm@10 1002 (defn quot
rlm@10 1003 "quot[ient] of dividing numerator by denominator."
rlm@10 1004 {:added "1.0"}
rlm@10 1005 [num div]
rlm@10 1006 (. clojure.lang.Numbers (quotient num div)))
rlm@10 1007
rlm@10 1008 (defn rem
rlm@10 1009 "remainder of dividing numerator by denominator."
rlm@10 1010 {:added "1.0"}
rlm@10 1011 [num div]
rlm@10 1012 (. clojure.lang.Numbers (remainder num div)))
rlm@10 1013
rlm@10 1014 (defn rationalize
rlm@10 1015 "returns the rational value of num"
rlm@10 1016 {:added "1.0"}
rlm@10 1017 [num]
rlm@10 1018 (. clojure.lang.Numbers (rationalize num)))
rlm@10 1019
rlm@10 1020 ;;Bit ops
rlm@10 1021
rlm@10 1022 (defn bit-not
rlm@10 1023 "Bitwise complement"
rlm@10 1024 {:inline (fn [x] `(. clojure.lang.Numbers (not ~x)))
rlm@10 1025 :added "1.0"}
rlm@10 1026 [x] (. clojure.lang.Numbers not x))
rlm@10 1027
rlm@10 1028
rlm@10 1029 (defn bit-and
rlm@10 1030 "Bitwise and"
rlm@10 1031 {:inline (fn [x y] `(. clojure.lang.Numbers (and ~x ~y)))
rlm@10 1032 :added "1.0"}
rlm@10 1033 [x y] (. clojure.lang.Numbers and x y))
rlm@10 1034
rlm@10 1035 (defn bit-or
rlm@10 1036 "Bitwise or"
rlm@10 1037 {:inline (fn [x y] `(. clojure.lang.Numbers (or ~x ~y)))
rlm@10 1038 :added "1.0"}
rlm@10 1039 [x y] (. clojure.lang.Numbers or x y))
rlm@10 1040
rlm@10 1041 (defn bit-xor
rlm@10 1042 "Bitwise exclusive or"
rlm@10 1043 {:inline (fn [x y] `(. clojure.lang.Numbers (xor ~x ~y)))
rlm@10 1044 :added "1.0"}
rlm@10 1045 [x y] (. clojure.lang.Numbers xor x y))
rlm@10 1046
rlm@10 1047 (defn bit-and-not
rlm@10 1048 "Bitwise and with complement"
rlm@10 1049 {:added "1.0"}
rlm@10 1050 [x y] (. clojure.lang.Numbers andNot x y))
rlm@10 1051
rlm@10 1052
rlm@10 1053 (defn bit-clear
rlm@10 1054 "Clear bit at index n"
rlm@10 1055 {:added "1.0"}
rlm@10 1056 [x n] (. clojure.lang.Numbers clearBit x n))
rlm@10 1057
rlm@10 1058 (defn bit-set
rlm@10 1059 "Set bit at index n"
rlm@10 1060 {:added "1.0"}
rlm@10 1061 [x n] (. clojure.lang.Numbers setBit x n))
rlm@10 1062
rlm@10 1063 (defn bit-flip
rlm@10 1064 "Flip bit at index n"
rlm@10 1065 {:added "1.0"}
rlm@10 1066 [x n] (. clojure.lang.Numbers flipBit x n))
rlm@10 1067
rlm@10 1068 (defn bit-test
rlm@10 1069 "Test bit at index n"
rlm@10 1070 {:added "1.0"}
rlm@10 1071 [x n] (. clojure.lang.Numbers testBit x n))
rlm@10 1072
rlm@10 1073
rlm@10 1074 (defn bit-shift-left
rlm@10 1075 "Bitwise shift left"
rlm@10 1076 {:inline (fn [x n] `(. clojure.lang.Numbers (shiftLeft ~x ~n)))
rlm@10 1077 :added "1.0"}
rlm@10 1078 [x n] (. clojure.lang.Numbers shiftLeft x n))
rlm@10 1079
rlm@10 1080 (defn bit-shift-right
rlm@10 1081 "Bitwise shift right"
rlm@10 1082 {:inline (fn [x n] `(. clojure.lang.Numbers (shiftRight ~x ~n)))
rlm@10 1083 :added "1.0"}
rlm@10 1084 [x n] (. clojure.lang.Numbers shiftRight x n))
rlm@10 1085
rlm@10 1086 (defn even?
rlm@10 1087 "Returns true if n is even, throws an exception if n is not an integer"
rlm@10 1088 {:added "1.0"}
rlm@10 1089 [n] (zero? (bit-and n 1)))
rlm@10 1090
rlm@10 1091 (defn odd?
rlm@10 1092 "Returns true if n is odd, throws an exception if n is not an integer"
rlm@10 1093 {:added "1.0"}
rlm@10 1094 [n] (not (even? n)))
rlm@10 1095
rlm@10 1096
rlm@10 1097 ;;
rlm@10 1098
rlm@10 1099 (defn complement
rlm@10 1100 "Takes a fn f and returns a fn that takes the same arguments as f,
rlm@10 1101 has the same effects, if any, and returns the opposite truth value."
rlm@10 1102 {:added "1.0"}
rlm@10 1103 [f]
rlm@10 1104 (fn
rlm@10 1105 ([] (not (f)))
rlm@10 1106 ([x] (not (f x)))
rlm@10 1107 ([x y] (not (f x y)))
rlm@10 1108 ([x y & zs] (not (apply f x y zs)))))
rlm@10 1109
rlm@10 1110 (defn constantly
rlm@10 1111 "Returns a function that takes any number of arguments and returns x."
rlm@10 1112 {:added "1.0"}
rlm@10 1113 [x] (fn [& args] x))
rlm@10 1114
rlm@10 1115 (defn identity
rlm@10 1116 "Returns its argument."
rlm@10 1117 {:added "1.0"}
rlm@10 1118 [x] x)
rlm@10 1119
rlm@10 1120 ;;Collection stuff
rlm@10 1121
rlm@10 1122
rlm@10 1123
rlm@10 1124
rlm@10 1125
rlm@10 1126 ;;list stuff
rlm@10 1127 (defn peek
rlm@10 1128 "For a list or queue, same as first, for a vector, same as, but much
rlm@10 1129 more efficient than, last. If the collection is empty, returns nil."
rlm@10 1130 {:added "1.0"}
rlm@10 1131 [coll] (. clojure.lang.RT (peek coll)))
rlm@10 1132
rlm@10 1133 (defn pop
rlm@10 1134 "For a list or queue, returns a new list/queue without the first
rlm@10 1135 item, for a vector, returns a new vector without the last item. If
rlm@10 1136 the collection is empty, throws an exception. Note - not the same
rlm@10 1137 as next/butlast."
rlm@10 1138 {:added "1.0"}
rlm@10 1139 [coll] (. clojure.lang.RT (pop coll)))
rlm@10 1140
rlm@10 1141 ;;map stuff
rlm@10 1142
rlm@10 1143 (defn contains?
rlm@10 1144 "Returns true if key is present in the given collection, otherwise
rlm@10 1145 returns false. Note that for numerically indexed collections like
rlm@10 1146 vectors and Java arrays, this tests if the numeric key is within the
rlm@10 1147 range of indexes. 'contains?' operates constant or logarithmic time;
rlm@10 1148 it will not perform a linear search for a value. See also 'some'."
rlm@10 1149 {:added "1.0"}
rlm@10 1150 [coll key] (. clojure.lang.RT (contains coll key)))
rlm@10 1151
rlm@10 1152 (defn get
rlm@10 1153 "Returns the value mapped to key, not-found or nil if key not present."
rlm@10 1154 {:inline (fn [m k & nf] `(. clojure.lang.RT (get ~m ~k ~@nf)))
rlm@10 1155 :inline-arities #{2 3}
rlm@10 1156 :added "1.0"}
rlm@10 1157 ([map key]
rlm@10 1158 (. clojure.lang.RT (get map key)))
rlm@10 1159 ([map key not-found]
rlm@10 1160 (. clojure.lang.RT (get map key not-found))))
rlm@10 1161
rlm@10 1162 (defn dissoc
rlm@10 1163 "dissoc[iate]. Returns a new map of the same (hashed/sorted) type,
rlm@10 1164 that does not contain a mapping for key(s)."
rlm@10 1165 {:added "1.0"}
rlm@10 1166 ([map] map)
rlm@10 1167 ([map key]
rlm@10 1168 (. clojure.lang.RT (dissoc map key)))
rlm@10 1169 ([map key & ks]
rlm@10 1170 (let [ret (dissoc map key)]
rlm@10 1171 (if ks
rlm@10 1172 (recur ret (first ks) (next ks))
rlm@10 1173 ret))))
rlm@10 1174
rlm@10 1175 (defn disj
rlm@10 1176 "disj[oin]. Returns a new set of the same (hashed/sorted) type, that
rlm@10 1177 does not contain key(s)."
rlm@10 1178 {:added "1.0"}
rlm@10 1179 ([set] set)
rlm@10 1180 ([^clojure.lang.IPersistentSet set key]
rlm@10 1181 (when set
rlm@10 1182 (. set (disjoin key))))
rlm@10 1183 ([set key & ks]
rlm@10 1184 (when set
rlm@10 1185 (let [ret (disj set key)]
rlm@10 1186 (if ks
rlm@10 1187 (recur ret (first ks) (next ks))
rlm@10 1188 ret)))))
rlm@10 1189
rlm@10 1190 (defn find
rlm@10 1191 "Returns the map entry for key, or nil if key not present."
rlm@10 1192 {:added "1.0"}
rlm@10 1193 [map key] (. clojure.lang.RT (find map key)))
rlm@10 1194
rlm@10 1195 (defn select-keys
rlm@10 1196 "Returns a map containing only those entries in map whose key is in keys"
rlm@10 1197 {:added "1.0"}
rlm@10 1198 [map keyseq]
rlm@10 1199 (loop [ret {} keys (seq keyseq)]
rlm@10 1200 (if keys
rlm@10 1201 (let [entry (. clojure.lang.RT (find map (first keys)))]
rlm@10 1202 (recur
rlm@10 1203 (if entry
rlm@10 1204 (conj ret entry)
rlm@10 1205 ret)
rlm@10 1206 (next keys)))
rlm@10 1207 ret)))
rlm@10 1208
rlm@10 1209 (defn keys
rlm@10 1210 "Returns a sequence of the map's keys."
rlm@10 1211 {:added "1.0"}
rlm@10 1212 [map] (. clojure.lang.RT (keys map)))
rlm@10 1213
rlm@10 1214 (defn vals
rlm@10 1215 "Returns a sequence of the map's values."
rlm@10 1216 {:added "1.0"}
rlm@10 1217 [map] (. clojure.lang.RT (vals map)))
rlm@10 1218
rlm@10 1219 (defn key
rlm@10 1220 "Returns the key of the map entry."
rlm@10 1221 {:added "1.0"}
rlm@10 1222 [^java.util.Map$Entry e]
rlm@10 1223 (. e (getKey)))
rlm@10 1224
rlm@10 1225 (defn val
rlm@10 1226 "Returns the value in the map entry."
rlm@10 1227 {:added "1.0"}
rlm@10 1228 [^java.util.Map$Entry e]
rlm@10 1229 (. e (getValue)))
rlm@10 1230
rlm@10 1231 (defn rseq
rlm@10 1232 "Returns, in constant time, a seq of the items in rev (which
rlm@10 1233 can be a vector or sorted-map), in reverse order. If rev is empty returns nil"
rlm@10 1234 {:added "1.0"}
rlm@10 1235 [^clojure.lang.Reversible rev]
rlm@10 1236 (. rev (rseq)))
rlm@10 1237
rlm@10 1238 (defn name
rlm@10 1239 "Returns the name String of a string, symbol or keyword."
rlm@10 1240 {:tag String
rlm@10 1241 :added "1.0"}
rlm@10 1242 [^clojure.lang.Named x]
rlm@10 1243 (if (string? x) x (. x (getName))))
rlm@10 1244
rlm@10 1245 (defn namespace
rlm@10 1246 "Returns the namespace String of a symbol or keyword, or nil if not present."
rlm@10 1247 {:tag String
rlm@10 1248 :added "1.0"}
rlm@10 1249 [^clojure.lang.Named x]
rlm@10 1250 (. x (getNamespace)))
rlm@10 1251
rlm@10 1252 (defmacro locking
rlm@10 1253 "Executes exprs in an implicit do, while holding the monitor of x.
rlm@10 1254 Will release the monitor of x in all circumstances."
rlm@10 1255 {:added "1.0"}
rlm@10 1256 [x & body]
rlm@10 1257 `(let [lockee# ~x]
rlm@10 1258 (try
rlm@10 1259 (monitor-enter lockee#)
rlm@10 1260 ~@body
rlm@10 1261 (finally
rlm@10 1262 (monitor-exit lockee#)))))
rlm@10 1263
rlm@10 1264 (defmacro ..
rlm@10 1265 "form => fieldName-symbol or (instanceMethodName-symbol args*)
rlm@10 1266
rlm@10 1267 Expands into a member access (.) of the first member on the first
rlm@10 1268 argument, followed by the next member on the result, etc. For
rlm@10 1269 instance:
rlm@10 1270
rlm@10 1271 (.. System (getProperties) (get \"os.name\"))
rlm@10 1272
rlm@10 1273 expands to:
rlm@10 1274
rlm@10 1275 (. (. System (getProperties)) (get \"os.name\"))
rlm@10 1276
rlm@10 1277 but is easier to write, read, and understand."
rlm@10 1278 {:added "1.0"}
rlm@10 1279 ([x form] `(. ~x ~form))
rlm@10 1280 ([x form & more] `(.. (. ~x ~form) ~@more)))
rlm@10 1281
rlm@10 1282 (defmacro ->
rlm@10 1283 "Threads the expr through the forms. Inserts x as the
rlm@10 1284 second item in the first form, making a list of it if it is not a
rlm@10 1285 list already. If there are more forms, inserts the first form as the
rlm@10 1286 second item in second form, etc."
rlm@10 1287 {:added "1.0"}
rlm@10 1288 ([x] x)
rlm@10 1289 ([x form] (if (seq? form)
rlm@10 1290 (with-meta `(~(first form) ~x ~@(next form)) (meta form))
rlm@10 1291 (list form x)))
rlm@10 1292 ([x form & more] `(-> (-> ~x ~form) ~@more)))
rlm@10 1293
rlm@10 1294 (defmacro ->>
rlm@10 1295 "Threads the expr through the forms. Inserts x as the
rlm@10 1296 last item in the first form, making a list of it if it is not a
rlm@10 1297 list already. If there are more forms, inserts the first form as the
rlm@10 1298 last item in second form, etc."
rlm@10 1299 {:added "1.1"}
rlm@10 1300 ([x form] (if (seq? form)
rlm@10 1301 (with-meta `(~(first form) ~@(next form) ~x) (meta form))
rlm@10 1302 (list form x)))
rlm@10 1303 ([x form & more] `(->> (->> ~x ~form) ~@more)))
rlm@10 1304
rlm@10 1305 ;;multimethods
rlm@10 1306 (def global-hierarchy)
rlm@10 1307
rlm@10 1308 (defmacro defmulti
rlm@10 1309 "Creates a new multimethod with the associated dispatch function.
rlm@10 1310 The docstring and attribute-map are optional.
rlm@10 1311
rlm@10 1312 Options are key-value pairs and may be one of:
rlm@10 1313 :default the default dispatch value, defaults to :default
rlm@10 1314 :hierarchy the isa? hierarchy to use for dispatching
rlm@10 1315 defaults to the global hierarchy"
rlm@10 1316 {:arglists '([name docstring? attr-map? dispatch-fn & options])
rlm@10 1317 :added "1.0"}
rlm@10 1318 [mm-name & options]
rlm@10 1319 (let [docstring (if (string? (first options))
rlm@10 1320 (first options)
rlm@10 1321 nil)
rlm@10 1322 options (if (string? (first options))
rlm@10 1323 (next options)
rlm@10 1324 options)
rlm@10 1325 m (if (map? (first options))
rlm@10 1326 (first options)
rlm@10 1327 {})
rlm@10 1328 options (if (map? (first options))
rlm@10 1329 (next options)
rlm@10 1330 options)
rlm@10 1331 dispatch-fn (first options)
rlm@10 1332 options (next options)
rlm@10 1333 m (assoc m :tag 'clojure.lang.MultiFn)
rlm@10 1334 m (if docstring
rlm@10 1335 (assoc m :doc docstring)
rlm@10 1336 m)
rlm@10 1337 m (if (meta mm-name)
rlm@10 1338 (conj (meta mm-name) m)
rlm@10 1339 m)]
rlm@10 1340 (when (= (count options) 1)
rlm@10 1341 (throw (Exception. "The syntax for defmulti has changed. Example: (defmulti name dispatch-fn :default dispatch-value)")))
rlm@10 1342 (let [options (apply hash-map options)
rlm@10 1343 default (get options :default :default)
rlm@10 1344 hierarchy (get options :hierarchy #'global-hierarchy)]
rlm@10 1345 `(let [v# (def ~mm-name)]
rlm@10 1346 (when-not (and (.hasRoot v#) (instance? clojure.lang.MultiFn (deref v#)))
rlm@10 1347 (def ~(with-meta mm-name m)
rlm@10 1348 (new clojure.lang.MultiFn ~(name mm-name) ~dispatch-fn ~default ~hierarchy)))))))
rlm@10 1349
rlm@10 1350 (defmacro defmethod
rlm@10 1351 "Creates and installs a new method of multimethod associated with dispatch-value. "
rlm@10 1352 {:added "1.0"}
rlm@10 1353 [multifn dispatch-val & fn-tail]
rlm@10 1354 `(. ~(with-meta multifn {:tag 'clojure.lang.MultiFn}) addMethod ~dispatch-val (fn ~@fn-tail)))
rlm@10 1355
rlm@10 1356 (defn remove-all-methods
rlm@10 1357 "Removes all of the methods of multimethod."
rlm@10 1358 {:added "1.2"}
rlm@10 1359 [^clojure.lang.MultiFn multifn]
rlm@10 1360 (.reset multifn))
rlm@10 1361
rlm@10 1362 (defn remove-method
rlm@10 1363 "Removes the method of multimethod associated with dispatch-value."
rlm@10 1364 {:added "1.0"}
rlm@10 1365 [^clojure.lang.MultiFn multifn dispatch-val]
rlm@10 1366 (. multifn removeMethod dispatch-val))
rlm@10 1367
rlm@10 1368 (defn prefer-method
rlm@10 1369 "Causes the multimethod to prefer matches of dispatch-val-x over dispatch-val-y
rlm@10 1370 when there is a conflict"
rlm@10 1371 {:added "1.0"}
rlm@10 1372 [^clojure.lang.MultiFn multifn dispatch-val-x dispatch-val-y]
rlm@10 1373 (. multifn preferMethod dispatch-val-x dispatch-val-y))
rlm@10 1374
rlm@10 1375 (defn methods
rlm@10 1376 "Given a multimethod, returns a map of dispatch values -> dispatch fns"
rlm@10 1377 {:added "1.0"}
rlm@10 1378 [^clojure.lang.MultiFn multifn] (.getMethodTable multifn))
rlm@10 1379
rlm@10 1380 (defn get-method
rlm@10 1381 "Given a multimethod and a dispatch value, returns the dispatch fn
rlm@10 1382 that would apply to that value, or nil if none apply and no default"
rlm@10 1383 {:added "1.0"}
rlm@10 1384 [^clojure.lang.MultiFn multifn dispatch-val] (.getMethod multifn dispatch-val))
rlm@10 1385
rlm@10 1386 (defn prefers
rlm@10 1387 "Given a multimethod, returns a map of preferred value -> set of other values"
rlm@10 1388 {:added "1.0"}
rlm@10 1389 [^clojure.lang.MultiFn multifn] (.getPreferTable multifn))
rlm@10 1390
rlm@10 1391 ;;;;;;;;; var stuff
rlm@10 1392
rlm@10 1393 (defmacro ^{:private true} assert-args [fnname & pairs]
rlm@10 1394 `(do (when-not ~(first pairs)
rlm@10 1395 (throw (IllegalArgumentException.
rlm@10 1396 ~(str fnname " requires " (second pairs)))))
rlm@10 1397 ~(let [more (nnext pairs)]
rlm@10 1398 (when more
rlm@10 1399 (list* `assert-args fnname more)))))
rlm@10 1400
rlm@10 1401 (defmacro if-let
rlm@10 1402 "bindings => binding-form test
rlm@10 1403
rlm@10 1404 If test is true, evaluates then with binding-form bound to the value of
rlm@10 1405 test, if not, yields else"
rlm@10 1406 {:added "1.0"}
rlm@10 1407 ([bindings then]
rlm@10 1408 `(if-let ~bindings ~then nil))
rlm@10 1409 ([bindings then else & oldform]
rlm@10 1410 (assert-args if-let
rlm@10 1411 (and (vector? bindings) (nil? oldform)) "a vector for its binding"
rlm@10 1412 (= 2 (count bindings)) "exactly 2 forms in binding vector")
rlm@10 1413 (let [form (bindings 0) tst (bindings 1)]
rlm@10 1414 `(let [temp# ~tst]
rlm@10 1415 (if temp#
rlm@10 1416 (let [~form temp#]
rlm@10 1417 ~then)
rlm@10 1418 ~else)))))
rlm@10 1419
rlm@10 1420 (defmacro when-let
rlm@10 1421 "bindings => binding-form test
rlm@10 1422
rlm@10 1423 When test is true, evaluates body with binding-form bound to the value of test"
rlm@10 1424 {:added "1.0"}
rlm@10 1425 [bindings & body]
rlm@10 1426 (assert-args when-let
rlm@10 1427 (vector? bindings) "a vector for its binding"
rlm@10 1428 (= 2 (count bindings)) "exactly 2 forms in binding vector")
rlm@10 1429 (let [form (bindings 0) tst (bindings 1)]
rlm@10 1430 `(let [temp# ~tst]
rlm@10 1431 (when temp#
rlm@10 1432 (let [~form temp#]
rlm@10 1433 ~@body)))))
rlm@10 1434
rlm@10 1435 (defn push-thread-bindings
rlm@10 1436 "WARNING: This is a low-level function. Prefer high-level macros like
rlm@10 1437 binding where ever possible.
rlm@10 1438
rlm@10 1439 Takes a map of Var/value pairs. Binds each Var to the associated value for
rlm@10 1440 the current thread. Each call *MUST* be accompanied by a matching call to
rlm@10 1441 pop-thread-bindings wrapped in a try-finally!
rlm@10 1442
rlm@10 1443 (push-thread-bindings bindings)
rlm@10 1444 (try
rlm@10 1445 ...
rlm@10 1446 (finally
rlm@10 1447 (pop-thread-bindings)))"
rlm@10 1448 {:added "1.1"}
rlm@10 1449 [bindings]
rlm@10 1450 (clojure.lang.Var/pushThreadBindings bindings))
rlm@10 1451
rlm@10 1452 (defn pop-thread-bindings
rlm@10 1453 "Pop one set of bindings pushed with push-binding before. It is an error to
rlm@10 1454 pop bindings without pushing before."
rlm@10 1455 {:added "1.1"}
rlm@10 1456 []
rlm@10 1457 (clojure.lang.Var/popThreadBindings))
rlm@10 1458
rlm@10 1459 (defn get-thread-bindings
rlm@10 1460 "Get a map with the Var/value pairs which is currently in effect for the
rlm@10 1461 current thread."
rlm@10 1462 {:added "1.1"}
rlm@10 1463 []
rlm@10 1464 (clojure.lang.Var/getThreadBindings))
rlm@10 1465
rlm@10 1466 (defmacro binding
rlm@10 1467 "binding => var-symbol init-expr
rlm@10 1468
rlm@10 1469 Creates new bindings for the (already-existing) vars, with the
rlm@10 1470 supplied initial values, executes the exprs in an implicit do, then
rlm@10 1471 re-establishes the bindings that existed before. The new bindings
rlm@10 1472 are made in parallel (unlike let); all init-exprs are evaluated
rlm@10 1473 before the vars are bound to their new values."
rlm@10 1474 {:added "1.0"}
rlm@10 1475 [bindings & body]
rlm@10 1476 (assert-args binding
rlm@10 1477 (vector? bindings) "a vector for its binding"
rlm@10 1478 (even? (count bindings)) "an even number of forms in binding vector")
rlm@10 1479 (let [var-ize (fn [var-vals]
rlm@10 1480 (loop [ret [] vvs (seq var-vals)]
rlm@10 1481 (if vvs
rlm@10 1482 (recur (conj (conj ret `(var ~(first vvs))) (second vvs))
rlm@10 1483 (next (next vvs)))
rlm@10 1484 (seq ret))))]
rlm@10 1485 `(let []
rlm@10 1486 (push-thread-bindings (hash-map ~@(var-ize bindings)))
rlm@10 1487 (try
rlm@10 1488 ~@body
rlm@10 1489 (finally
rlm@10 1490 (pop-thread-bindings))))))
rlm@10 1491
rlm@10 1492 (defn with-bindings*
rlm@10 1493 "Takes a map of Var/value pairs. Installs for the given Vars the associated
rlm@10 1494 values as thread-local bindings. Then calls f with the supplied arguments.
rlm@10 1495 Pops the installed bindings after f returned. Returns whatever f returns."
rlm@10 1496 {:added "1.1"}
rlm@10 1497 [binding-map f & args]
rlm@10 1498 (push-thread-bindings binding-map)
rlm@10 1499 (try
rlm@10 1500 (apply f args)
rlm@10 1501 (finally
rlm@10 1502 (pop-thread-bindings))))
rlm@10 1503
rlm@10 1504 (defmacro with-bindings
rlm@10 1505 "Takes a map of Var/value pairs. Installs for the given Vars the associated
rlm@10 1506 values as thread-local bindings. The executes body. Pops the installed
rlm@10 1507 bindings after body was evaluated. Returns the value of body."
rlm@10 1508 {:added "1.1"}
rlm@10 1509 [binding-map & body]
rlm@10 1510 `(with-bindings* ~binding-map (fn [] ~@body)))
rlm@10 1511
rlm@10 1512 (defn bound-fn*
rlm@10 1513 "Returns a function, which will install the same bindings in effect as in
rlm@10 1514 the thread at the time bound-fn* was called and then call f with any given
rlm@10 1515 arguments. This may be used to define a helper function which runs on a
rlm@10 1516 different thread, but needs the same bindings in place."
rlm@10 1517 {:added "1.1"}
rlm@10 1518 [f]
rlm@10 1519 (let [bindings (get-thread-bindings)]
rlm@10 1520 (fn [& args]
rlm@10 1521 (apply with-bindings* bindings f args))))
rlm@10 1522
rlm@10 1523 (defmacro bound-fn
rlm@10 1524 "Returns a function defined by the given fntail, which will install the
rlm@10 1525 same bindings in effect as in the thread at the time bound-fn was called.
rlm@10 1526 This may be used to define a helper function which runs on a different
rlm@10 1527 thread, but needs the same bindings in place."
rlm@10 1528 {:added "1.1"}
rlm@10 1529 [& fntail]
rlm@10 1530 `(bound-fn* (fn ~@fntail)))
rlm@10 1531
rlm@10 1532 (defn find-var
rlm@10 1533 "Returns the global var named by the namespace-qualified symbol, or
rlm@10 1534 nil if no var with that name."
rlm@10 1535 {:added "1.0"}
rlm@10 1536 [sym] (. clojure.lang.Var (find sym)))
rlm@10 1537
rlm@10 1538 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Refs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
rlm@10 1539 (defn ^{:private true}
rlm@10 1540 setup-reference [^clojure.lang.ARef r options]
rlm@10 1541 (let [opts (apply hash-map options)]
rlm@10 1542 (when (:meta opts)
rlm@10 1543 (.resetMeta r (:meta opts)))
rlm@10 1544 (when (:validator opts)
rlm@10 1545 (.setValidator r (:validator opts)))
rlm@10 1546 r))
rlm@10 1547
rlm@10 1548 (defn agent
rlm@10 1549 "Creates and returns an agent with an initial value of state and
rlm@10 1550 zero or more options (in any order):
rlm@10 1551
rlm@10 1552 :meta metadata-map
rlm@10 1553
rlm@10 1554 :validator validate-fn
rlm@10 1555
rlm@10 1556 :error-handler handler-fn
rlm@10 1557
rlm@10 1558 :error-mode mode-keyword
rlm@10 1559
rlm@10 1560 If metadata-map is supplied, it will be come the metadata on the
rlm@10 1561 agent. validate-fn must be nil or a side-effect-free fn of one
rlm@10 1562 argument, which will be passed the intended new state on any state
rlm@10 1563 change. If the new state is unacceptable, the validate-fn should
rlm@10 1564 return false or throw an exception. handler-fn is called if an
rlm@10 1565 action throws an exception or if validate-fn rejects a new state --
rlm@10 1566 see set-error-handler! for details. The mode-keyword may be either
rlm@10 1567 :continue (the default if an error-handler is given) or :fail (the
rlm@10 1568 default if no error-handler is given) -- see set-error-mode! for
rlm@10 1569 details."
rlm@10 1570 {:added "1.0"}
rlm@10 1571 ([state & options]
rlm@10 1572 (let [a (new clojure.lang.Agent state)
rlm@10 1573 opts (apply hash-map options)]
rlm@10 1574 (setup-reference a options)
rlm@10 1575 (when (:error-handler opts)
rlm@10 1576 (.setErrorHandler a (:error-handler opts)))
rlm@10 1577 (.setErrorMode a (or (:error-mode opts)
rlm@10 1578 (if (:error-handler opts) :continue :fail)))
rlm@10 1579 a)))
rlm@10 1580
rlm@10 1581 (defn send
rlm@10 1582 "Dispatch an action to an agent. Returns the agent immediately.
rlm@10 1583 Subsequently, in a thread from a thread pool, the state of the agent
rlm@10 1584 will be set to the value of:
rlm@10 1585
rlm@10 1586 (apply action-fn state-of-agent args)"
rlm@10 1587 {:added "1.0"}
rlm@10 1588 [^clojure.lang.Agent a f & args]
rlm@10 1589 (. a (dispatch f args false)))
rlm@10 1590
rlm@10 1591 (defn send-off
rlm@10 1592 "Dispatch a potentially blocking action to an agent. Returns the
rlm@10 1593 agent immediately. Subsequently, in a separate thread, the state of
rlm@10 1594 the agent will be set to the value of:
rlm@10 1595
rlm@10 1596 (apply action-fn state-of-agent args)"
rlm@10 1597 {:added "1.0"}
rlm@10 1598 [^clojure.lang.Agent a f & args]
rlm@10 1599 (. a (dispatch f args true)))
rlm@10 1600
rlm@10 1601 (defn release-pending-sends
rlm@10 1602 "Normally, actions sent directly or indirectly during another action
rlm@10 1603 are held until the action completes (changes the agent's
rlm@10 1604 state). This function can be used to dispatch any pending sent
rlm@10 1605 actions immediately. This has no impact on actions sent during a
rlm@10 1606 transaction, which are still held until commit. If no action is
rlm@10 1607 occurring, does nothing. Returns the number of actions dispatched."
rlm@10 1608 {:added "1.0"}
rlm@10 1609 [] (clojure.lang.Agent/releasePendingSends))
rlm@10 1610
rlm@10 1611 (defn add-watch
rlm@10 1612 "Alpha - subject to change.
rlm@10 1613 Adds a watch function to an agent/atom/var/ref reference. The watch
rlm@10 1614 fn must be a fn of 4 args: a key, the reference, its old-state, its
rlm@10 1615 new-state. Whenever the reference's state might have been changed,
rlm@10 1616 any registered watches will have their functions called. The watch fn
rlm@10 1617 will be called synchronously, on the agent's thread if an agent,
rlm@10 1618 before any pending sends if agent or ref. Note that an atom's or
rlm@10 1619 ref's state may have changed again prior to the fn call, so use
rlm@10 1620 old/new-state rather than derefing the reference. Note also that watch
rlm@10 1621 fns may be called from multiple threads simultaneously. Var watchers
rlm@10 1622 are triggered only by root binding changes, not thread-local
rlm@10 1623 set!s. Keys must be unique per reference, and can be used to remove
rlm@10 1624 the watch with remove-watch, but are otherwise considered opaque by
rlm@10 1625 the watch mechanism."
rlm@10 1626 {:added "1.0"}
rlm@10 1627 [^clojure.lang.IRef reference key fn] (.addWatch reference key fn))
rlm@10 1628
rlm@10 1629 (defn remove-watch
rlm@10 1630 "Alpha - subject to change.
rlm@10 1631 Removes a watch (set by add-watch) from a reference"
rlm@10 1632 {:added "1.0"}
rlm@10 1633 [^clojure.lang.IRef reference key]
rlm@10 1634 (.removeWatch reference key))
rlm@10 1635
rlm@10 1636 (defn agent-error
rlm@10 1637 "Returns the exception thrown during an asynchronous action of the
rlm@10 1638 agent if the agent is failed. Returns nil if the agent is not
rlm@10 1639 failed."
rlm@10 1640 {:added "1.2"}
rlm@10 1641 [^clojure.lang.Agent a] (.getError a))
rlm@10 1642
rlm@10 1643 (defn restart-agent
rlm@10 1644 "When an agent is failed, changes the agent state to new-state and
rlm@10 1645 then un-fails the agent so that sends are allowed again. If
rlm@10 1646 a :clear-actions true option is given, any actions queued on the
rlm@10 1647 agent that were being held while it was failed will be discarded,
rlm@10 1648 otherwise those held actions will proceed. The new-state must pass
rlm@10 1649 the validator if any, or restart will throw an exception and the
rlm@10 1650 agent will remain failed with its old state and error. Watchers, if
rlm@10 1651 any, will NOT be notified of the new state. Throws an exception if
rlm@10 1652 the agent is not failed."
rlm@10 1653 {:added "1.2"}
rlm@10 1654 [^clojure.lang.Agent a, new-state & options]
rlm@10 1655 (let [opts (apply hash-map options)]
rlm@10 1656 (.restart a new-state (if (:clear-actions opts) true false))))
rlm@10 1657
rlm@10 1658 (defn set-error-handler!
rlm@10 1659 "Sets the error-handler of agent a to handler-fn. If an action
rlm@10 1660 being run by the agent throws an exception or doesn't pass the
rlm@10 1661 validator fn, handler-fn will be called with two arguments: the
rlm@10 1662 agent and the exception."
rlm@10 1663 {:added "1.2"}
rlm@10 1664 [^clojure.lang.Agent a, handler-fn]
rlm@10 1665 (.setErrorHandler a handler-fn))
rlm@10 1666
rlm@10 1667 (defn error-handler
rlm@10 1668 "Returns the error-handler of agent a, or nil if there is none.
rlm@10 1669 See set-error-handler!"
rlm@10 1670 {:added "1.2"}
rlm@10 1671 [^clojure.lang.Agent a]
rlm@10 1672 (.getErrorHandler a))
rlm@10 1673
rlm@10 1674 (defn set-error-mode!
rlm@10 1675 "Sets the error-mode of agent a to mode-keyword, which must be
rlm@10 1676 either :fail or :continue. If an action being run by the agent
rlm@10 1677 throws an exception or doesn't pass the validator fn, an
rlm@10 1678 error-handler may be called (see set-error-handler!), after which,
rlm@10 1679 if the mode is :continue, the agent will continue as if neither the
rlm@10 1680 action that caused the error nor the error itself ever happened.
rlm@10 1681
rlm@10 1682 If the mode is :fail, the agent will become failed and will stop
rlm@10 1683 accepting new 'send' and 'send-off' actions, and any previously
rlm@10 1684 queued actions will be held until a 'restart-agent'. Deref will
rlm@10 1685 still work, returning the state of the agent before the error."
rlm@10 1686 {:added "1.2"}
rlm@10 1687 [^clojure.lang.Agent a, mode-keyword]
rlm@10 1688 (.setErrorMode a mode-keyword))
rlm@10 1689
rlm@10 1690 (defn error-mode
rlm@10 1691 "Returns the error-mode of agent a. See set-error-mode!"
rlm@10 1692 {:added "1.2"}
rlm@10 1693 [^clojure.lang.Agent a]
rlm@10 1694 (.getErrorMode a))
rlm@10 1695
rlm@10 1696 (defn agent-errors
rlm@10 1697 "DEPRECATED: Use 'agent-error' instead.
rlm@10 1698 Returns a sequence of the exceptions thrown during asynchronous
rlm@10 1699 actions of the agent."
rlm@10 1700 {:added "1.0"
rlm@10 1701 :deprecated "1.2"}
rlm@10 1702 [a]
rlm@10 1703 (when-let [e (agent-error a)]
rlm@10 1704 (list e)))
rlm@10 1705
rlm@10 1706 (defn clear-agent-errors
rlm@10 1707 "DEPRECATED: Use 'restart-agent' instead.
rlm@10 1708 Clears any exceptions thrown during asynchronous actions of the
rlm@10 1709 agent, allowing subsequent actions to occur."
rlm@10 1710 {:added "1.0"
rlm@10 1711 :deprecated "1.2"}
rlm@10 1712 [^clojure.lang.Agent a] (restart-agent a (.deref a)))
rlm@10 1713
rlm@10 1714 (defn shutdown-agents
rlm@10 1715 "Initiates a shutdown of the thread pools that back the agent
rlm@10 1716 system. Running actions will complete, but no new actions will be
rlm@10 1717 accepted"
rlm@10 1718 {:added "1.0"}
rlm@10 1719 [] (. clojure.lang.Agent shutdown))
rlm@10 1720
rlm@10 1721 (defn ref
rlm@10 1722 "Creates and returns a Ref with an initial value of x and zero or
rlm@10 1723 more options (in any order):
rlm@10 1724
rlm@10 1725 :meta metadata-map
rlm@10 1726
rlm@10 1727 :validator validate-fn
rlm@10 1728
rlm@10 1729 :min-history (default 0)
rlm@10 1730 :max-history (default 10)
rlm@10 1731
rlm@10 1732 If metadata-map is supplied, it will be come the metadata on the
rlm@10 1733 ref. validate-fn must be nil or a side-effect-free fn of one
rlm@10 1734 argument, which will be passed the intended new state on any state
rlm@10 1735 change. If the new state is unacceptable, the validate-fn should
rlm@10 1736 return false or throw an exception. validate-fn will be called on
rlm@10 1737 transaction commit, when all refs have their final values.
rlm@10 1738
rlm@10 1739 Normally refs accumulate history dynamically as needed to deal with
rlm@10 1740 read demands. If you know in advance you will need history you can
rlm@10 1741 set :min-history to ensure it will be available when first needed (instead
rlm@10 1742 of after a read fault). History is limited, and the limit can be set
rlm@10 1743 with :max-history."
rlm@10 1744 {:added "1.0"}
rlm@10 1745 ([x] (new clojure.lang.Ref x))
rlm@10 1746 ([x & options]
rlm@10 1747 (let [r ^clojure.lang.Ref (setup-reference (ref x) options)
rlm@10 1748 opts (apply hash-map options)]
rlm@10 1749 (when (:max-history opts)
rlm@10 1750 (.setMaxHistory r (:max-history opts)))
rlm@10 1751 (when (:min-history opts)
rlm@10 1752 (.setMinHistory r (:min-history opts)))
rlm@10 1753 r)))
rlm@10 1754
rlm@10 1755 (defn deref
rlm@10 1756 "Also reader macro: @ref/@agent/@var/@atom/@delay/@future. Within a transaction,
rlm@10 1757 returns the in-transaction-value of ref, else returns the
rlm@10 1758 most-recently-committed value of ref. When applied to a var, agent
rlm@10 1759 or atom, returns its current state. When applied to a delay, forces
rlm@10 1760 it if not already forced. When applied to a future, will block if
rlm@10 1761 computation not complete"
rlm@10 1762 {:added "1.0"}
rlm@10 1763 [^clojure.lang.IDeref ref] (.deref ref))
rlm@10 1764
rlm@10 1765 (defn atom
rlm@10 1766 "Creates and returns an Atom with an initial value of x and zero or
rlm@10 1767 more options (in any order):
rlm@10 1768
rlm@10 1769 :meta metadata-map
rlm@10 1770
rlm@10 1771 :validator validate-fn
rlm@10 1772
rlm@10 1773 If metadata-map is supplied, it will be come the metadata on the
rlm@10 1774 atom. validate-fn must be nil or a side-effect-free fn of one
rlm@10 1775 argument, which will be passed the intended new state on any state
rlm@10 1776 change. If the new state is unacceptable, the validate-fn should
rlm@10 1777 return false or throw an exception."
rlm@10 1778 {:added "1.0"}
rlm@10 1779 ([x] (new clojure.lang.Atom x))
rlm@10 1780 ([x & options] (setup-reference (atom x) options)))
rlm@10 1781
rlm@10 1782 (defn swap!
rlm@10 1783 "Atomically swaps the value of atom to be:
rlm@10 1784 (apply f current-value-of-atom args). Note that f may be called
rlm@10 1785 multiple times, and thus should be free of side effects. Returns
rlm@10 1786 the value that was swapped in."
rlm@10 1787 {:added "1.0"}
rlm@10 1788 ([^clojure.lang.Atom atom f] (.swap atom f))
rlm@10 1789 ([^clojure.lang.Atom atom f x] (.swap atom f x))
rlm@10 1790 ([^clojure.lang.Atom atom f x y] (.swap atom f x y))
rlm@10 1791 ([^clojure.lang.Atom atom f x y & args] (.swap atom f x y args)))
rlm@10 1792
rlm@10 1793 (defn compare-and-set!
rlm@10 1794 "Atomically sets the value of atom to newval if and only if the
rlm@10 1795 current value of the atom is identical to oldval. Returns true if
rlm@10 1796 set happened, else false"
rlm@10 1797 {:added "1.0"}
rlm@10 1798 [^clojure.lang.Atom atom oldval newval] (.compareAndSet atom oldval newval))
rlm@10 1799
rlm@10 1800 (defn reset!
rlm@10 1801 "Sets the value of atom to newval without regard for the
rlm@10 1802 current value. Returns newval."
rlm@10 1803 {:added "1.0"}
rlm@10 1804 [^clojure.lang.Atom atom newval] (.reset atom newval))
rlm@10 1805
rlm@10 1806 (defn set-validator!
rlm@10 1807 "Sets the validator-fn for a var/ref/agent/atom. validator-fn must be nil or a
rlm@10 1808 side-effect-free fn of one argument, which will be passed the intended
rlm@10 1809 new state on any state change. If the new state is unacceptable, the
rlm@10 1810 validator-fn should return false or throw an exception. If the current state (root
rlm@10 1811 value if var) is not acceptable to the new validator, an exception
rlm@10 1812 will be thrown and the validator will not be changed."
rlm@10 1813 {:added "1.0"}
rlm@10 1814 [^clojure.lang.IRef iref validator-fn] (. iref (setValidator validator-fn)))
rlm@10 1815
rlm@10 1816 (defn get-validator
rlm@10 1817 "Gets the validator-fn for a var/ref/agent/atom."
rlm@10 1818 {:added "1.0"}
rlm@10 1819 [^clojure.lang.IRef iref] (. iref (getValidator)))
rlm@10 1820
rlm@10 1821 (defn alter-meta!
rlm@10 1822 "Atomically sets the metadata for a namespace/var/ref/agent/atom to be:
rlm@10 1823
rlm@10 1824 (apply f its-current-meta args)
rlm@10 1825
rlm@10 1826 f must be free of side-effects"
rlm@10 1827 {:added "1.0"}
rlm@10 1828 [^clojure.lang.IReference iref f & args] (.alterMeta iref f args))
rlm@10 1829
rlm@10 1830 (defn reset-meta!
rlm@10 1831 "Atomically resets the metadata for a namespace/var/ref/agent/atom"
rlm@10 1832 {:added "1.0"}
rlm@10 1833 [^clojure.lang.IReference iref metadata-map] (.resetMeta iref metadata-map))
rlm@10 1834
rlm@10 1835 (defn commute
rlm@10 1836 "Must be called in a transaction. Sets the in-transaction-value of
rlm@10 1837 ref to:
rlm@10 1838
rlm@10 1839 (apply fun in-transaction-value-of-ref args)
rlm@10 1840
rlm@10 1841 and returns the in-transaction-value of ref.
rlm@10 1842
rlm@10 1843 At the commit point of the transaction, sets the value of ref to be:
rlm@10 1844
rlm@10 1845 (apply fun most-recently-committed-value-of-ref args)
rlm@10 1846
rlm@10 1847 Thus fun should be commutative, or, failing that, you must accept
rlm@10 1848 last-one-in-wins behavior. commute allows for more concurrency than
rlm@10 1849 ref-set."
rlm@10 1850 {:added "1.0"}
rlm@10 1851
rlm@10 1852 [^clojure.lang.Ref ref fun & args]
rlm@10 1853 (. ref (commute fun args)))
rlm@10 1854
rlm@10 1855 (defn alter
rlm@10 1856 "Must be called in a transaction. Sets the in-transaction-value of
rlm@10 1857 ref to:
rlm@10 1858
rlm@10 1859 (apply fun in-transaction-value-of-ref args)
rlm@10 1860
rlm@10 1861 and returns the in-transaction-value of ref."
rlm@10 1862 {:added "1.0"}
rlm@10 1863 [^clojure.lang.Ref ref fun & args]
rlm@10 1864 (. ref (alter fun args)))
rlm@10 1865
rlm@10 1866 (defn ref-set
rlm@10 1867 "Must be called in a transaction. Sets the value of ref.
rlm@10 1868 Returns val."
rlm@10 1869 {:added "1.0"}
rlm@10 1870 [^clojure.lang.Ref ref val]
rlm@10 1871 (. ref (set val)))
rlm@10 1872
rlm@10 1873 (defn ref-history-count
rlm@10 1874 "Returns the history count of a ref"
rlm@10 1875 {:added "1.1"}
rlm@10 1876 [^clojure.lang.Ref ref]
rlm@10 1877 (.getHistoryCount ref))
rlm@10 1878
rlm@10 1879 (defn ref-min-history
rlm@10 1880 "Gets the min-history of a ref, or sets it and returns the ref"
rlm@10 1881 {:added "1.1"}
rlm@10 1882 ([^clojure.lang.Ref ref]
rlm@10 1883 (.getMinHistory ref))
rlm@10 1884 ([^clojure.lang.Ref ref n]
rlm@10 1885 (.setMinHistory ref n)))
rlm@10 1886
rlm@10 1887 (defn ref-max-history
rlm@10 1888 "Gets the max-history of a ref, or sets it and returns the ref"
rlm@10 1889 {:added "1.1"}
rlm@10 1890 ([^clojure.lang.Ref ref]
rlm@10 1891 (.getMaxHistory ref))
rlm@10 1892 ([^clojure.lang.Ref ref n]
rlm@10 1893 (.setMaxHistory ref n)))
rlm@10 1894
rlm@10 1895 (defn ensure
rlm@10 1896 "Must be called in a transaction. Protects the ref from modification
rlm@10 1897 by other transactions. Returns the in-transaction-value of
rlm@10 1898 ref. Allows for more concurrency than (ref-set ref @ref)"
rlm@10 1899 {:added "1.0"}
rlm@10 1900 [^clojure.lang.Ref ref]
rlm@10 1901 (. ref (touch))
rlm@10 1902 (. ref (deref)))
rlm@10 1903
rlm@10 1904 (defmacro sync
rlm@10 1905 "transaction-flags => TBD, pass nil for now
rlm@10 1906
rlm@10 1907 Runs the exprs (in an implicit do) in a transaction that encompasses
rlm@10 1908 exprs and any nested calls. Starts a transaction if none is already
rlm@10 1909 running on this thread. Any uncaught exception will abort the
rlm@10 1910 transaction and flow out of sync. The exprs may be run more than
rlm@10 1911 once, but any effects on Refs will be atomic."
rlm@10 1912 {:added "1.0"}
rlm@10 1913 [flags-ignored-for-now & body]
rlm@10 1914 `(. clojure.lang.LockingTransaction
rlm@10 1915 (runInTransaction (fn [] ~@body))))
rlm@10 1916
rlm@10 1917
rlm@10 1918 (defmacro io!
rlm@10 1919 "If an io! block occurs in a transaction, throws an
rlm@10 1920 IllegalStateException, else runs body in an implicit do. If the
rlm@10 1921 first expression in body is a literal string, will use that as the
rlm@10 1922 exception message."
rlm@10 1923 {:added "1.0"}
rlm@10 1924 [& body]
rlm@10 1925 (let [message (when (string? (first body)) (first body))
rlm@10 1926 body (if message (next body) body)]
rlm@10 1927 `(if (clojure.lang.LockingTransaction/isRunning)
rlm@10 1928 (throw (new IllegalStateException ~(or message "I/O in transaction")))
rlm@10 1929 (do ~@body))))
rlm@10 1930
rlm@10 1931 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fn stuff ;;;;;;;;;;;;;;;;
rlm@10 1932
rlm@10 1933
rlm@10 1934 (defn comp
rlm@10 1935 "Takes a set of functions and returns a fn that is the composition
rlm@10 1936 of those fns. The returned fn takes a variable number of args,
rlm@10 1937 applies the rightmost of fns to the args, the next
rlm@10 1938 fn (right-to-left) to the result, etc."
rlm@10 1939 {:added "1.0"}
rlm@10 1940 ([f] f)
rlm@10 1941 ([f g]
rlm@10 1942 (fn
rlm@10 1943 ([] (f (g)))
rlm@10 1944 ([x] (f (g x)))
rlm@10 1945 ([x y] (f (g x y)))
rlm@10 1946 ([x y z] (f (g x y z)))
rlm@10 1947 ([x y z & args] (f (apply g x y z args)))))
rlm@10 1948 ([f g h]
rlm@10 1949 (fn
rlm@10 1950 ([] (f (g (h))))
rlm@10 1951 ([x] (f (g (h x))))
rlm@10 1952 ([x y] (f (g (h x y))))
rlm@10 1953 ([x y z] (f (g (h x y z))))
rlm@10 1954 ([x y z & args] (f (g (apply h x y z args))))))
rlm@10 1955 ([f1 f2 f3 & fs]
rlm@10 1956 (let [fs (reverse (list* f1 f2 f3 fs))]
rlm@10 1957 (fn [& args]
rlm@10 1958 (loop [ret (apply (first fs) args) fs (next fs)]
rlm@10 1959 (if fs
rlm@10 1960 (recur ((first fs) ret) (next fs))
rlm@10 1961 ret))))))
rlm@10 1962
rlm@10 1963 (defn juxt
rlm@10 1964 "Alpha - name subject to change.
rlm@10 1965 Takes a set of functions and returns a fn that is the juxtaposition
rlm@10 1966 of those fns. The returned fn takes a variable number of args, and
rlm@10 1967 returns a vector containing the result of applying each fn to the
rlm@10 1968 args (left-to-right).
rlm@10 1969 ((juxt a b c) x) => [(a x) (b x) (c x)]"
rlm@10 1970 {:added "1.1"}
rlm@10 1971 ([f]
rlm@10 1972 (fn
rlm@10 1973 ([] [(f)])
rlm@10 1974 ([x] [(f x)])
rlm@10 1975 ([x y] [(f x y)])
rlm@10 1976 ([x y z] [(f x y z)])
rlm@10 1977 ([x y z & args] [(apply f x y z args)])))
rlm@10 1978 ([f g]
rlm@10 1979 (fn
rlm@10 1980 ([] [(f) (g)])
rlm@10 1981 ([x] [(f x) (g x)])
rlm@10 1982 ([x y] [(f x y) (g x y)])
rlm@10 1983 ([x y z] [(f x y z) (g x y z)])
rlm@10 1984 ([x y z & args] [(apply f x y z args) (apply g x y z args)])))
rlm@10 1985 ([f g h]
rlm@10 1986 (fn
rlm@10 1987 ([] [(f) (g) (h)])
rlm@10 1988 ([x] [(f x) (g x) (h x)])
rlm@10 1989 ([x y] [(f x y) (g x y) (h x y)])
rlm@10 1990 ([x y z] [(f x y z) (g x y z) (h x y z)])
rlm@10 1991 ([x y z & args] [(apply f x y z args) (apply g x y z args) (apply h x y z args)])))
rlm@10 1992 ([f g h & fs]
rlm@10 1993 (let [fs (list* f g h fs)]
rlm@10 1994 (fn
rlm@10 1995 ([] (reduce #(conj %1 (%2)) [] fs))
rlm@10 1996 ([x] (reduce #(conj %1 (%2 x)) [] fs))
rlm@10 1997 ([x y] (reduce #(conj %1 (%2 x y)) [] fs))
rlm@10 1998 ([x y z] (reduce #(conj %1 (%2 x y z)) [] fs))
rlm@10 1999 ([x y z & args] (reduce #(conj %1 (apply %2 x y z args)) [] fs))))))
rlm@10 2000
rlm@10 2001 (defn partial
rlm@10 2002 "Takes a function f and fewer than the normal arguments to f, and
rlm@10 2003 returns a fn that takes a variable number of additional args. When
rlm@10 2004 called, the returned function calls f with args + additional args."
rlm@10 2005 {:added "1.0"}
rlm@10 2006 ([f arg1]
rlm@10 2007 (fn [& args] (apply f arg1 args)))
rlm@10 2008 ([f arg1 arg2]
rlm@10 2009 (fn [& args] (apply f arg1 arg2 args)))
rlm@10 2010 ([f arg1 arg2 arg3]
rlm@10 2011 (fn [& args] (apply f arg1 arg2 arg3 args)))
rlm@10 2012 ([f arg1 arg2 arg3 & more]
rlm@10 2013 (fn [& args] (apply f arg1 arg2 arg3 (concat more args)))))
rlm@10 2014
rlm@10 2015 ;;;;;;;;;;;;;;;;;;; sequence fns ;;;;;;;;;;;;;;;;;;;;;;;
rlm@10 2016 (defn sequence
rlm@10 2017 "Coerces coll to a (possibly empty) sequence, if it is not already
rlm@10 2018 one. Will not force a lazy seq. (sequence nil) yields ()"
rlm@10 2019 {:added "1.0"}
rlm@10 2020 [coll]
rlm@10 2021 (if (seq? coll) coll
rlm@10 2022 (or (seq coll) ())))
rlm@10 2023
rlm@10 2024 (defn every?
rlm@10 2025 "Returns true if (pred x) is logical true for every x in coll, else
rlm@10 2026 false."
rlm@10 2027 {:tag Boolean
rlm@10 2028 :added "1.0"}
rlm@10 2029 [pred coll]
rlm@10 2030 (cond
rlm@10 2031 (nil? (seq coll)) true
rlm@10 2032 (pred (first coll)) (recur pred (next coll))
rlm@10 2033 :else false))
rlm@10 2034
rlm@10 2035 (def
rlm@10 2036 ^{:tag Boolean
rlm@10 2037 :doc "Returns false if (pred x) is logical true for every x in
rlm@10 2038 coll, else true."
rlm@10 2039 :arglists '([pred coll])
rlm@10 2040 :added "1.0"}
rlm@10 2041 not-every? (comp not every?))
rlm@10 2042
rlm@10 2043 (defn some
rlm@10 2044 "Returns the first logical true value of (pred x) for any x in coll,
rlm@10 2045 else nil. One common idiom is to use a set as pred, for example
rlm@10 2046 this will return :fred if :fred is in the sequence, otherwise nil:
rlm@10 2047 (some #{:fred} coll)"
rlm@10 2048 {:added "1.0"}
rlm@10 2049 [pred coll]
rlm@10 2050 (when (seq coll)
rlm@10 2051 (or (pred (first coll)) (recur pred (next coll)))))
rlm@10 2052
rlm@10 2053 (def
rlm@10 2054 ^{:tag Boolean
rlm@10 2055 :doc "Returns false if (pred x) is logical true for any x in coll,
rlm@10 2056 else true."
rlm@10 2057 :arglists '([pred coll])
rlm@10 2058 :added "1.0"}
rlm@10 2059 not-any? (comp not some))
rlm@10 2060
rlm@10 2061 ;will be redefed later with arg checks
rlm@10 2062 (defmacro dotimes
rlm@10 2063 "bindings => name n
rlm@10 2064
rlm@10 2065 Repeatedly executes body (presumably for side-effects) with name
rlm@10 2066 bound to integers from 0 through n-1."
rlm@10 2067 {:added "1.0"}
rlm@10 2068 [bindings & body]
rlm@10 2069 (let [i (first bindings)
rlm@10 2070 n (second bindings)]
rlm@10 2071 `(let [n# (int ~n)]
rlm@10 2072 (loop [~i (int 0)]
rlm@10 2073 (when (< ~i n#)
rlm@10 2074 ~@body
rlm@10 2075 (recur (inc ~i)))))))
rlm@10 2076
rlm@10 2077 (defn map
rlm@10 2078 "Returns a lazy sequence consisting of the result of applying f to the
rlm@10 2079 set of first items of each coll, followed by applying f to the set
rlm@10 2080 of second items in each coll, until any one of the colls is
rlm@10 2081 exhausted. Any remaining items in other colls are ignored. Function
rlm@10 2082 f should accept number-of-colls arguments."
rlm@10 2083 {:added "1.0"}
rlm@10 2084 ([f coll]
rlm@10 2085 (lazy-seq
rlm@10 2086 (when-let [s (seq coll)]
rlm@10 2087 (if (chunked-seq? s)
rlm@10 2088 (let [c (chunk-first s)
rlm@10 2089 size (int (count c))
rlm@10 2090 b (chunk-buffer size)]
rlm@10 2091 (dotimes [i size]
rlm@10 2092 (chunk-append b (f (.nth c i))))
rlm@10 2093 (chunk-cons (chunk b) (map f (chunk-rest s))))
rlm@10 2094 (cons (f (first s)) (map f (rest s)))))))
rlm@10 2095 ([f c1 c2]
rlm@10 2096 (lazy-seq
rlm@10 2097 (let [s1 (seq c1) s2 (seq c2)]
rlm@10 2098 (when (and s1 s2)
rlm@10 2099 (cons (f (first s1) (first s2))
rlm@10 2100 (map f (rest s1) (rest s2)))))))
rlm@10 2101 ([f c1 c2 c3]
rlm@10 2102 (lazy-seq
rlm@10 2103 (let [s1 (seq c1) s2 (seq c2) s3 (seq c3)]
rlm@10 2104 (when (and s1 s2 s3)
rlm@10 2105 (cons (f (first s1) (first s2) (first s3))
rlm@10 2106 (map f (rest s1) (rest s2) (rest s3)))))))
rlm@10 2107 ([f c1 c2 c3 & colls]
rlm@10 2108 (let [step (fn step [cs]
rlm@10 2109 (lazy-seq
rlm@10 2110 (let [ss (map seq cs)]
rlm@10 2111 (when (every? identity ss)
rlm@10 2112 (cons (map first ss) (step (map rest ss)))))))]
rlm@10 2113 (map #(apply f %) (step (conj colls c3 c2 c1))))))
rlm@10 2114
rlm@10 2115 (defn mapcat
rlm@10 2116 "Returns the result of applying concat to the result of applying map
rlm@10 2117 to f and colls. Thus function f should return a collection."
rlm@10 2118 {:added "1.0"}
rlm@10 2119 [f & colls]
rlm@10 2120 (apply concat (apply map f colls)))
rlm@10 2121
rlm@10 2122 (defn filter
rlm@10 2123 "Returns a lazy sequence of the items in coll for which
rlm@10 2124 (pred item) returns true. pred must be free of side-effects."
rlm@10 2125 {:added "1.0"}
rlm@10 2126 ([pred coll]
rlm@10 2127 (lazy-seq
rlm@10 2128 (when-let [s (seq coll)]
rlm@10 2129 (if (chunked-seq? s)
rlm@10 2130 (let [c (chunk-first s)
rlm@10 2131 size (count c)
rlm@10 2132 b (chunk-buffer size)]
rlm@10 2133 (dotimes [i size]
rlm@10 2134 (when (pred (.nth c i))
rlm@10 2135 (chunk-append b (.nth c i))))
rlm@10 2136 (chunk-cons (chunk b) (filter pred (chunk-rest s))))
rlm@10 2137 (let [f (first s) r (rest s)]
rlm@10 2138 (if (pred f)
rlm@10 2139 (cons f (filter pred r))
rlm@10 2140 (filter pred r))))))))
rlm@10 2141
rlm@10 2142
rlm@10 2143 (defn remove
rlm@10 2144 "Returns a lazy sequence of the items in coll for which
rlm@10 2145 (pred item) returns false. pred must be free of side-effects."
rlm@10 2146 {:added "1.0"}
rlm@10 2147 [pred coll]
rlm@10 2148 (filter (complement pred) coll))
rlm@10 2149
rlm@10 2150 (defn take
rlm@10 2151 "Returns a lazy sequence of the first n items in coll, or all items if
rlm@10 2152 there are fewer than n."
rlm@10 2153 {:added "1.0"}
rlm@10 2154 [n coll]
rlm@10 2155 (lazy-seq
rlm@10 2156 (when (pos? n)
rlm@10 2157 (when-let [s (seq coll)]
rlm@10 2158 (cons (first s) (take (dec n) (rest s)))))))
rlm@10 2159
rlm@10 2160 (defn take-while
rlm@10 2161 "Returns a lazy sequence of successive items from coll while
rlm@10 2162 (pred item) returns true. pred must be free of side-effects."
rlm@10 2163 {:added "1.0"}
rlm@10 2164 [pred coll]
rlm@10 2165 (lazy-seq
rlm@10 2166 (when-let [s (seq coll)]
rlm@10 2167 (when (pred (first s))
rlm@10 2168 (cons (first s) (take-while pred (rest s)))))))
rlm@10 2169
rlm@10 2170 (defn drop
rlm@10 2171 "Returns a lazy sequence of all but the first n items in coll."
rlm@10 2172 {:added "1.0"}
rlm@10 2173 [n coll]
rlm@10 2174 (let [step (fn [n coll]
rlm@10 2175 (let [s (seq coll)]
rlm@10 2176 (if (and (pos? n) s)
rlm@10 2177 (recur (dec n) (rest s))
rlm@10 2178 s)))]
rlm@10 2179 (lazy-seq (step n coll))))
rlm@10 2180
rlm@10 2181 (defn drop-last
rlm@10 2182 "Return a lazy sequence of all but the last n (default 1) items in coll"
rlm@10 2183 {:added "1.0"}
rlm@10 2184 ([s] (drop-last 1 s))
rlm@10 2185 ([n s] (map (fn [x _] x) s (drop n s))))
rlm@10 2186
rlm@10 2187 (defn take-last
rlm@10 2188 "Returns a seq of the last n items in coll. Depending on the type
rlm@10 2189 of coll may be no better than linear time. For vectors, see also subvec."
rlm@10 2190 {:added "1.1"}
rlm@10 2191 [n coll]
rlm@10 2192 (loop [s (seq coll), lead (seq (drop n coll))]
rlm@10 2193 (if lead
rlm@10 2194 (recur (next s) (next lead))
rlm@10 2195 s)))
rlm@10 2196
rlm@10 2197 (defn drop-while
rlm@10 2198 "Returns a lazy sequence of the items in coll starting from the first
rlm@10 2199 item for which (pred item) returns nil."
rlm@10 2200 {:added "1.0"}
rlm@10 2201 [pred coll]
rlm@10 2202 (let [step (fn [pred coll]
rlm@10 2203 (let [s (seq coll)]
rlm@10 2204 (if (and s (pred (first s)))
rlm@10 2205 (recur pred (rest s))
rlm@10 2206 s)))]
rlm@10 2207 (lazy-seq (step pred coll))))
rlm@10 2208
rlm@10 2209 (defn cycle
rlm@10 2210 "Returns a lazy (infinite!) sequence of repetitions of the items in coll."
rlm@10 2211 {:added "1.0"}
rlm@10 2212 [coll] (lazy-seq
rlm@10 2213 (when-let [s (seq coll)]
rlm@10 2214 (concat s (cycle s)))))
rlm@10 2215
rlm@10 2216 (defn split-at
rlm@10 2217 "Returns a vector of [(take n coll) (drop n coll)]"
rlm@10 2218 {:added "1.0"}
rlm@10 2219 [n coll]
rlm@10 2220 [(take n coll) (drop n coll)])
rlm@10 2221
rlm@10 2222 (defn split-with
rlm@10 2223 "Returns a vector of [(take-while pred coll) (drop-while pred coll)]"
rlm@10 2224 {:added "1.0"}
rlm@10 2225 [pred coll]
rlm@10 2226 [(take-while pred coll) (drop-while pred coll)])
rlm@10 2227
rlm@10 2228 (defn repeat
rlm@10 2229 "Returns a lazy (infinite!, or length n if supplied) sequence of xs."
rlm@10 2230 {:added "1.0"}
rlm@10 2231 ([x] (lazy-seq (cons x (repeat x))))
rlm@10 2232 ([n x] (take n (repeat x))))
rlm@10 2233
rlm@10 2234 (defn replicate
rlm@10 2235 "Returns a lazy seq of n xs."
rlm@10 2236 {:added "1.0"}
rlm@10 2237 [n x] (take n (repeat x)))
rlm@10 2238
rlm@10 2239 (defn iterate
rlm@10 2240 "Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"
rlm@10 2241 {:added "1.0"}
rlm@10 2242 [f x] (cons x (lazy-seq (iterate f (f x)))))
rlm@10 2243
rlm@10 2244 (defn range
rlm@10 2245 "Returns a lazy seq of nums from start (inclusive) to end
rlm@10 2246 (exclusive), by step, where start defaults to 0, step to 1, and end
rlm@10 2247 to infinity."
rlm@10 2248 {:added "1.0"}
rlm@10 2249 ([] (range 0 Double/POSITIVE_INFINITY 1))
rlm@10 2250 ([end] (range 0 end 1))
rlm@10 2251 ([start end] (range start end 1))
rlm@10 2252 ([start end step]
rlm@10 2253 (lazy-seq
rlm@10 2254 (let [b (chunk-buffer 32)
rlm@10 2255 comp (if (pos? step) < >)]
rlm@10 2256 (loop [i start]
rlm@10 2257 (if (and (< (count b) 32)
rlm@10 2258 (comp i end))
rlm@10 2259 (do
rlm@10 2260 (chunk-append b i)
rlm@10 2261 (recur (+ i step)))
rlm@10 2262 (chunk-cons (chunk b)
rlm@10 2263 (when (comp i end)
rlm@10 2264 (range i end step)))))))))
rlm@10 2265
rlm@10 2266 (defn merge
rlm@10 2267 "Returns a map that consists of the rest of the maps conj-ed onto
rlm@10 2268 the first. If a key occurs in more than one map, the mapping from
rlm@10 2269 the latter (left-to-right) will be the mapping in the result."
rlm@10 2270 {:added "1.0"}
rlm@10 2271 [& maps]
rlm@10 2272 (when (some identity maps)
rlm@10 2273 (reduce #(conj (or %1 {}) %2) maps)))
rlm@10 2274
rlm@10 2275 (defn merge-with
rlm@10 2276 "Returns a map that consists of the rest of the maps conj-ed onto
rlm@10 2277 the first. If a key occurs in more than one map, the mapping(s)
rlm@10 2278 from the latter (left-to-right) will be combined with the mapping in
rlm@10 2279 the result by calling (f val-in-result val-in-latter)."
rlm@10 2280 {:added "1.0"}
rlm@10 2281 [f & maps]
rlm@10 2282 (when (some identity maps)
rlm@10 2283 (let [merge-entry (fn [m e]
rlm@10 2284 (let [k (key e) v (val e)]
rlm@10 2285 (if (contains? m k)
rlm@10 2286 (assoc m k (f (get m k) v))
rlm@10 2287 (assoc m k v))))
rlm@10 2288 merge2 (fn [m1 m2]
rlm@10 2289 (reduce merge-entry (or m1 {}) (seq m2)))]
rlm@10 2290 (reduce merge2 maps))))
rlm@10 2291
rlm@10 2292
rlm@10 2293
rlm@10 2294 (defn zipmap
rlm@10 2295 "Returns a map with the keys mapped to the corresponding vals."
rlm@10 2296 {:added "1.0"}
rlm@10 2297 [keys vals]
rlm@10 2298 (loop [map {}
rlm@10 2299 ks (seq keys)
rlm@10 2300 vs (seq vals)]
rlm@10 2301 (if (and ks vs)
rlm@10 2302 (recur (assoc map (first ks) (first vs))
rlm@10 2303 (next ks)
rlm@10 2304 (next vs))
rlm@10 2305 map)))
rlm@10 2306
rlm@10 2307 (defmacro declare
rlm@10 2308 "defs the supplied var names with no bindings, useful for making forward declarations."
rlm@10 2309 {:added "1.0"}
rlm@10 2310 [& names] `(do ~@(map #(list 'def (vary-meta % assoc :declared true)) names)))
rlm@10 2311
rlm@10 2312 (defn line-seq
rlm@10 2313 "Returns the lines of text from rdr as a lazy sequence of strings.
rlm@10 2314 rdr must implement java.io.BufferedReader."
rlm@10 2315 {:added "1.0"}
rlm@10 2316 [^java.io.BufferedReader rdr]
rlm@10 2317 (when-let [line (.readLine rdr)]
rlm@10 2318 (cons line (lazy-seq (line-seq rdr)))))
rlm@10 2319
rlm@10 2320 (defn comparator
rlm@10 2321 "Returns an implementation of java.util.Comparator based upon pred."
rlm@10 2322 {:added "1.0"}
rlm@10 2323 [pred]
rlm@10 2324 (fn [x y]
rlm@10 2325 (cond (pred x y) -1 (pred y x) 1 :else 0)))
rlm@10 2326
rlm@10 2327 (defn sort
rlm@10 2328 "Returns a sorted sequence of the items in coll. If no comparator is
rlm@10 2329 supplied, uses compare. comparator must
rlm@10 2330 implement java.util.Comparator."
rlm@10 2331 {:added "1.0"}
rlm@10 2332 ([coll]
rlm@10 2333 (sort compare coll))
rlm@10 2334 ([^java.util.Comparator comp coll]
rlm@10 2335 (if (seq coll)
rlm@10 2336 (let [a (to-array coll)]
rlm@10 2337 (. java.util.Arrays (sort a comp))
rlm@10 2338 (seq a))
rlm@10 2339 ())))
rlm@10 2340
rlm@10 2341 (defn sort-by
rlm@10 2342 "Returns a sorted sequence of the items in coll, where the sort
rlm@10 2343 order is determined by comparing (keyfn item). If no comparator is
rlm@10 2344 supplied, uses compare. comparator must
rlm@10 2345 implement java.util.Comparator."
rlm@10 2346 {:added "1.0"}
rlm@10 2347 ([keyfn coll]
rlm@10 2348 (sort-by keyfn compare coll))
rlm@10 2349 ([keyfn ^java.util.Comparator comp coll]
rlm@10 2350 (sort (fn [x y] (. comp (compare (keyfn x) (keyfn y)))) coll)))
rlm@10 2351
rlm@10 2352 (defn partition
rlm@10 2353 "Returns a lazy sequence of lists of n items each, at offsets step
rlm@10 2354 apart. If step is not supplied, defaults to n, i.e. the partitions
rlm@10 2355 do not overlap. If a pad collection is supplied, use its elements as
rlm@10 2356 necessary to complete last partition upto n items. In case there are
rlm@10 2357 not enough padding elements, return a partition with less than n items."
rlm@10 2358 {:added "1.0"}
rlm@10 2359 ([n coll]
rlm@10 2360 (partition n n coll))
rlm@10 2361 ([n step coll]
rlm@10 2362 (lazy-seq
rlm@10 2363 (when-let [s (seq coll)]
rlm@10 2364 (let [p (take n s)]
rlm@10 2365 (when (= n (count p))
rlm@10 2366 (cons p (partition n step (drop step s))))))))
rlm@10 2367 ([n step pad coll]
rlm@10 2368 (lazy-seq
rlm@10 2369 (when-let [s (seq coll)]
rlm@10 2370 (let [p (take n s)]
rlm@10 2371 (if (= n (count p))
rlm@10 2372 (cons p (partition n step pad (drop step s)))
rlm@10 2373 (list (take n (concat p pad)))))))))
rlm@10 2374
rlm@10 2375 ;; evaluation
rlm@10 2376
rlm@10 2377 (defn eval
rlm@10 2378 "Evaluates the form data structure (not text!) and returns the result."
rlm@10 2379 {:added "1.0"}
rlm@10 2380 [form] (. clojure.lang.Compiler (eval form)))
rlm@10 2381
rlm@10 2382 (defmacro doseq
rlm@10 2383 "Repeatedly executes body (presumably for side-effects) with
rlm@10 2384 bindings and filtering as provided by \"for\". Does not retain
rlm@10 2385 the head of the sequence. Returns nil."
rlm@10 2386 {:added "1.0"}
rlm@10 2387 [seq-exprs & body]
rlm@10 2388 (assert-args doseq
rlm@10 2389 (vector? seq-exprs) "a vector for its binding"
rlm@10 2390 (even? (count seq-exprs)) "an even number of forms in binding vector")
rlm@10 2391 (let [step (fn step [recform exprs]
rlm@10 2392 (if-not exprs
rlm@10 2393 [true `(do ~@body)]
rlm@10 2394 (let [k (first exprs)
rlm@10 2395 v (second exprs)]
rlm@10 2396 (if (keyword? k)
rlm@10 2397 (let [steppair (step recform (nnext exprs))
rlm@10 2398 needrec (steppair 0)
rlm@10 2399 subform (steppair 1)]
rlm@10 2400 (cond
rlm@10 2401 (= k :let) [needrec `(let ~v ~subform)]
rlm@10 2402 (= k :while) [false `(when ~v
rlm@10 2403 ~subform
rlm@10 2404 ~@(when needrec [recform]))]
rlm@10 2405 (= k :when) [false `(if ~v
rlm@10 2406 (do
rlm@10 2407 ~subform
rlm@10 2408 ~@(when needrec [recform]))
rlm@10 2409 ~recform)]))
rlm@10 2410 (let [seq- (gensym "seq_")
rlm@10 2411 chunk- (with-meta (gensym "chunk_")
rlm@10 2412 {:tag 'clojure.lang.IChunk})
rlm@10 2413 count- (gensym "count_")
rlm@10 2414 i- (gensym "i_")
rlm@10 2415 recform `(recur (next ~seq-) nil (int 0) (int 0))
rlm@10 2416 steppair (step recform (nnext exprs))
rlm@10 2417 needrec (steppair 0)
rlm@10 2418 subform (steppair 1)
rlm@10 2419 recform-chunk
rlm@10 2420 `(recur ~seq- ~chunk- ~count- (unchecked-inc ~i-))
rlm@10 2421 steppair-chunk (step recform-chunk (nnext exprs))
rlm@10 2422 subform-chunk (steppair-chunk 1)]
rlm@10 2423 [true
rlm@10 2424 `(loop [~seq- (seq ~v), ~chunk- nil,
rlm@10 2425 ~count- (int 0), ~i- (int 0)]
rlm@10 2426 (if (< ~i- ~count-)
rlm@10 2427 (let [~k (.nth ~chunk- ~i-)]
rlm@10 2428 ~subform-chunk
rlm@10 2429 ~@(when needrec [recform-chunk]))
rlm@10 2430 (when-let [~seq- (seq ~seq-)]
rlm@10 2431 (if (chunked-seq? ~seq-)
rlm@10 2432 (let [c# (chunk-first ~seq-)]
rlm@10 2433 (recur (chunk-rest ~seq-) c#
rlm@10 2434 (int (count c#)) (int 0)))
rlm@10 2435 (let [~k (first ~seq-)]
rlm@10 2436 ~subform
rlm@10 2437 ~@(when needrec [recform]))))))])))))]
rlm@10 2438 (nth (step nil (seq seq-exprs)) 1)))
rlm@10 2439
rlm@10 2440 (defn dorun
rlm@10 2441 "When lazy sequences are produced via functions that have side
rlm@10 2442 effects, any effects other than those needed to produce the first
rlm@10 2443 element in the seq do not occur until the seq is consumed. dorun can
rlm@10 2444 be used to force any effects. Walks through the successive nexts of
rlm@10 2445 the seq, does not retain the head and returns nil."
rlm@10 2446 {:added "1.0"}
rlm@10 2447 ([coll]
rlm@10 2448 (when (seq coll)
rlm@10 2449 (recur (next coll))))
rlm@10 2450 ([n coll]
rlm@10 2451 (when (and (seq coll) (pos? n))
rlm@10 2452 (recur (dec n) (next coll)))))
rlm@10 2453
rlm@10 2454 (defn doall
rlm@10 2455 "When lazy sequences are produced via functions that have side
rlm@10 2456 effects, any effects other than those needed to produce the first
rlm@10 2457 element in the seq do not occur until the seq is consumed. doall can
rlm@10 2458 be used to force any effects. Walks through the successive nexts of
rlm@10 2459 the seq, retains the head and returns it, thus causing the entire
rlm@10 2460 seq to reside in memory at one time."
rlm@10 2461 {:added "1.0"}
rlm@10 2462 ([coll]
rlm@10 2463 (dorun coll)
rlm@10 2464 coll)
rlm@10 2465 ([n coll]
rlm@10 2466 (dorun n coll)
rlm@10 2467 coll))
rlm@10 2468
rlm@10 2469 (defn await
rlm@10 2470 "Blocks the current thread (indefinitely!) until all actions
rlm@10 2471 dispatched thus far, from this thread or agent, to the agent(s) have
rlm@10 2472 occurred. Will block on failed agents. Will never return if
rlm@10 2473 a failed agent is restarted with :clear-actions true."
rlm@10 2474 {:added "1.0"}
rlm@10 2475 [& agents]
rlm@10 2476 (io! "await in transaction"
rlm@10 2477 (when *agent*
rlm@10 2478 (throw (new Exception "Can't await in agent action")))
rlm@10 2479 (let [latch (new java.util.concurrent.CountDownLatch (count agents))
rlm@10 2480 count-down (fn [agent] (. latch (countDown)) agent)]
rlm@10 2481 (doseq [agent agents]
rlm@10 2482 (send agent count-down))
rlm@10 2483 (. latch (await)))))
rlm@10 2484
rlm@10 2485 (defn await1 [^clojure.lang.Agent a]
rlm@10 2486 (when (pos? (.getQueueCount a))
rlm@10 2487 (await a))
rlm@10 2488 a)
rlm@10 2489
rlm@10 2490 (defn await-for
rlm@10 2491 "Blocks the current thread until all actions dispatched thus
rlm@10 2492 far (from this thread or agent) to the agents have occurred, or the
rlm@10 2493 timeout (in milliseconds) has elapsed. Returns nil if returning due
rlm@10 2494 to timeout, non-nil otherwise."
rlm@10 2495 {:added "1.0"}
rlm@10 2496 [timeout-ms & agents]
rlm@10 2497 (io! "await-for in transaction"
rlm@10 2498 (when *agent*
rlm@10 2499 (throw (new Exception "Can't await in agent action")))
rlm@10 2500 (let [latch (new java.util.concurrent.CountDownLatch (count agents))
rlm@10 2501 count-down (fn [agent] (. latch (countDown)) agent)]
rlm@10 2502 (doseq [agent agents]
rlm@10 2503 (send agent count-down))
rlm@10 2504 (. latch (await timeout-ms (. java.util.concurrent.TimeUnit MILLISECONDS))))))
rlm@10 2505
rlm@10 2506 (defmacro dotimes
rlm@10 2507 "bindings => name n
rlm@10 2508
rlm@10 2509 Repeatedly executes body (presumably for side-effects) with name
rlm@10 2510 bound to integers from 0 through n-1."
rlm@10 2511 {:added "1.0"}
rlm@10 2512 [bindings & body]
rlm@10 2513 (assert-args dotimes
rlm@10 2514 (vector? bindings) "a vector for its binding"
rlm@10 2515 (= 2 (count bindings)) "exactly 2 forms in binding vector")
rlm@10 2516 (let [i (first bindings)
rlm@10 2517 n (second bindings)]
rlm@10 2518 `(let [n# (int ~n)]
rlm@10 2519 (loop [~i (int 0)]
rlm@10 2520 (when (< ~i n#)
rlm@10 2521 ~@body
rlm@10 2522 (recur (unchecked-inc ~i)))))))
rlm@10 2523
rlm@10 2524 #_(defn into
rlm@10 2525 "Returns a new coll consisting of to-coll with all of the items of
rlm@10 2526 from-coll conjoined."
rlm@10 2527 {:added "1.0"}
rlm@10 2528 [to from]
rlm@10 2529 (let [ret to items (seq from)]
rlm@10 2530 (if items
rlm@10 2531 (recur (conj ret (first items)) (next items))
rlm@10 2532 ret)))
rlm@10 2533
rlm@10 2534 ;;;;;;;;;;;;;;;;;;;;; editable collections ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
rlm@10 2535 (defn transient
rlm@10 2536 "Alpha - subject to change.
rlm@10 2537 Returns a new, transient version of the collection, in constant time."
rlm@10 2538 {:added "1.1"}
rlm@10 2539 [^clojure.lang.IEditableCollection coll]
rlm@10 2540 (.asTransient coll))
rlm@10 2541
rlm@10 2542 (defn persistent!
rlm@10 2543 "Alpha - subject to change.
rlm@10 2544 Returns a new, persistent version of the transient collection, in
rlm@10 2545 constant time. The transient collection cannot be used after this
rlm@10 2546 call, any such use will throw an exception."
rlm@10 2547 {:added "1.1"}
rlm@10 2548 [^clojure.lang.ITransientCollection coll]
rlm@10 2549 (.persistent coll))
rlm@10 2550
rlm@10 2551 (defn conj!
rlm@10 2552 "Alpha - subject to change.
rlm@10 2553 Adds x to the transient collection, and return coll. The 'addition'
rlm@10 2554 may happen at different 'places' depending on the concrete type."
rlm@10 2555 {:added "1.1"}
rlm@10 2556 [^clojure.lang.ITransientCollection coll x]
rlm@10 2557 (.conj coll x))
rlm@10 2558
rlm@10 2559 (defn assoc!
rlm@10 2560 "Alpha - subject to change.
rlm@10 2561 When applied to a transient map, adds mapping of key(s) to
rlm@10 2562 val(s). When applied to a transient vector, sets the val at index.
rlm@10 2563 Note - index must be <= (count vector). Returns coll."
rlm@10 2564 {:added "1.1"}
rlm@10 2565 ([^clojure.lang.ITransientAssociative coll key val] (.assoc coll key val))
rlm@10 2566 ([^clojure.lang.ITransientAssociative coll key val & kvs]
rlm@10 2567 (let [ret (.assoc coll key val)]
rlm@10 2568 (if kvs
rlm@10 2569 (recur ret (first kvs) (second kvs) (nnext kvs))
rlm@10 2570 ret))))
rlm@10 2571
rlm@10 2572 (defn dissoc!
rlm@10 2573 "Alpha - subject to change.
rlm@10 2574 Returns a transient map that doesn't contain a mapping for key(s)."
rlm@10 2575 {:added "1.1"}
rlm@10 2576 ([^clojure.lang.ITransientMap map key] (.without map key))
rlm@10 2577 ([^clojure.lang.ITransientMap map key & ks]
rlm@10 2578 (let [ret (.without map key)]
rlm@10 2579 (if ks
rlm@10 2580 (recur ret (first ks) (next ks))
rlm@10 2581 ret))))
rlm@10 2582
rlm@10 2583 (defn pop!
rlm@10 2584 "Alpha - subject to change.
rlm@10 2585 Removes the last item from a transient vector. If
rlm@10 2586 the collection is empty, throws an exception. Returns coll"
rlm@10 2587 {:added "1.1"}
rlm@10 2588 [^clojure.lang.ITransientVector coll]
rlm@10 2589 (.pop coll))
rlm@10 2590
rlm@10 2591 (defn disj!
rlm@10 2592 "Alpha - subject to change.
rlm@10 2593 disj[oin]. Returns a transient set of the same (hashed/sorted) type, that
rlm@10 2594 does not contain key(s)."
rlm@10 2595 {:added "1.1"}
rlm@10 2596 ([set] set)
rlm@10 2597 ([^clojure.lang.ITransientSet set key]
rlm@10 2598 (. set (disjoin key)))
rlm@10 2599 ([set key & ks]
rlm@10 2600 (let [ret (disj set key)]
rlm@10 2601 (if ks
rlm@10 2602 (recur ret (first ks) (next ks))
rlm@10 2603 ret))))
rlm@10 2604
rlm@10 2605 ;redef into with batch support
rlm@10 2606 (defn into
rlm@10 2607 "Returns a new coll consisting of to-coll with all of the items of
rlm@10 2608 from-coll conjoined."
rlm@10 2609 {:added "1.0"}
rlm@10 2610 [to from]
rlm@10 2611 (if (instance? clojure.lang.IEditableCollection to)
rlm@10 2612 (persistent! (reduce conj! (transient to) from))
rlm@10 2613 (reduce conj to from)))
rlm@10 2614
rlm@10 2615 (defmacro import
rlm@10 2616 "import-list => (package-symbol class-name-symbols*)
rlm@10 2617
rlm@10 2618 For each name in class-name-symbols, adds a mapping from name to the
rlm@10 2619 class named by package.name to the current namespace. Use :import in the ns
rlm@10 2620 macro in preference to calling this directly."
rlm@10 2621 {:added "1.0"}
rlm@10 2622 [& import-symbols-or-lists]
rlm@10 2623 (let [specs (map #(if (and (seq? %) (= 'quote (first %))) (second %) %)
rlm@10 2624 import-symbols-or-lists)]
rlm@10 2625 `(do ~@(map #(list 'clojure.core/import* %)
rlm@10 2626 (reduce (fn [v spec]
rlm@10 2627 (if (symbol? spec)
rlm@10 2628 (conj v (name spec))
rlm@10 2629 (let [p (first spec) cs (rest spec)]
rlm@10 2630 (into v (map #(str p "." %) cs)))))
rlm@10 2631 [] specs)))))
rlm@10 2632
rlm@10 2633 (defn into-array
rlm@10 2634 "Returns an array with components set to the values in aseq. The array's
rlm@10 2635 component type is type if provided, or the type of the first value in
rlm@10 2636 aseq if present, or Object. All values in aseq must be compatible with
rlm@10 2637 the component type. Class objects for the primitive types can be obtained
rlm@10 2638 using, e.g., Integer/TYPE."
rlm@10 2639 {:added "1.0"}
rlm@10 2640 ([aseq]
rlm@10 2641 (clojure.lang.RT/seqToTypedArray (seq aseq)))
rlm@10 2642 ([type aseq]
rlm@10 2643 (clojure.lang.RT/seqToTypedArray type (seq aseq))))
rlm@10 2644
rlm@10 2645 (defn ^{:private true}
rlm@10 2646 array [& items]
rlm@10 2647 (into-array items))
rlm@10 2648
rlm@10 2649 (defn ^Class class
rlm@10 2650 "Returns the Class of x"
rlm@10 2651 {:added "1.0"}
rlm@10 2652 [^Object x] (if (nil? x) x (. x (getClass))))
rlm@10 2653
rlm@10 2654 (defn type
rlm@10 2655 "Returns the :type metadata of x, or its Class if none"
rlm@10 2656 {:added "1.0"}
rlm@10 2657 [x]
rlm@10 2658 (or (:type (meta x)) (class x)))
rlm@10 2659
rlm@10 2660 (defn num
rlm@10 2661 "Coerce to Number"
rlm@10 2662 {:tag Number
rlm@10 2663 :inline (fn [x] `(. clojure.lang.Numbers (num ~x)))
rlm@10 2664 :added "1.0"}
rlm@10 2665 [x] (. clojure.lang.Numbers (num x)))
rlm@10 2666
rlm@10 2667 (defn long
rlm@10 2668 "Coerce to long"
rlm@10 2669 {:tag Long
rlm@10 2670 :inline (fn [x] `(. clojure.lang.RT (longCast ~x)))
rlm@10 2671 :added "1.0"}
rlm@10 2672 [^Number x] (clojure.lang.RT/longCast x))
rlm@10 2673
rlm@10 2674 (defn float
rlm@10 2675 "Coerce to float"
rlm@10 2676 {:tag Float
rlm@10 2677 :inline (fn [x] `(. clojure.lang.RT (floatCast ~x)))
rlm@10 2678 :added "1.0"}
rlm@10 2679 [^Number x] (clojure.lang.RT/floatCast x))
rlm@10 2680
rlm@10 2681 (defn double
rlm@10 2682 "Coerce to double"
rlm@10 2683 {:tag Double
rlm@10 2684 :inline (fn [x] `(. clojure.lang.RT (doubleCast ~x)))
rlm@10 2685 :added "1.0"}
rlm@10 2686 [^Number x] (clojure.lang.RT/doubleCast x))
rlm@10 2687
rlm@10 2688 (defn short
rlm@10 2689 "Coerce to short"
rlm@10 2690 {:tag Short
rlm@10 2691 :inline (fn [x] `(. clojure.lang.RT (shortCast ~x)))
rlm@10 2692 :added "1.0"}
rlm@10 2693 [^Number x] (clojure.lang.RT/shortCast x))
rlm@10 2694
rlm@10 2695 (defn byte
rlm@10 2696 "Coerce to byte"
rlm@10 2697 {:tag Byte
rlm@10 2698 :inline (fn [x] `(. clojure.lang.RT (byteCast ~x)))
rlm@10 2699 :added "1.0"}
rlm@10 2700 [^Number x] (clojure.lang.RT/byteCast x))
rlm@10 2701
rlm@10 2702 (defn char
rlm@10 2703 "Coerce to char"
rlm@10 2704 {:tag Character
rlm@10 2705 :inline (fn [x] `(. clojure.lang.RT (charCast ~x)))
rlm@10 2706 :added "1.1"}
rlm@10 2707 [x] (. clojure.lang.RT (charCast x)))
rlm@10 2708
rlm@10 2709 (defn boolean
rlm@10 2710 "Coerce to boolean"
rlm@10 2711 {
rlm@10 2712 :inline (fn [x] `(. clojure.lang.RT (booleanCast ~x)))
rlm@10 2713 :added "1.0"}
rlm@10 2714 [x] (clojure.lang.RT/booleanCast x))
rlm@10 2715
rlm@10 2716 (defn number?
rlm@10 2717 "Returns true if x is a Number"
rlm@10 2718 {:added "1.0"}
rlm@10 2719 [x]
rlm@10 2720 (instance? Number x))
rlm@10 2721
rlm@10 2722 (defn integer?
rlm@10 2723 "Returns true if n is an integer"
rlm@10 2724 {:added "1.0"}
rlm@10 2725 [n]
rlm@10 2726 (or (instance? Integer n)
rlm@10 2727 (instance? Long n)
rlm@10 2728 (instance? BigInteger n)
rlm@10 2729 (instance? Short n)
rlm@10 2730 (instance? Byte n)))
rlm@10 2731
rlm@10 2732 (defn mod
rlm@10 2733 "Modulus of num and div. Truncates toward negative infinity."
rlm@10 2734 {:added "1.0"}
rlm@10 2735 [num div]
rlm@10 2736 (let [m (rem num div)]
rlm@10 2737 (if (or (zero? m) (pos? (* num div)))
rlm@10 2738 m
rlm@10 2739 (+ m div))))
rlm@10 2740
rlm@10 2741 (defn ratio?
rlm@10 2742 "Returns true if n is a Ratio"
rlm@10 2743 {:added "1.0"}
rlm@10 2744 [n] (instance? clojure.lang.Ratio n))
rlm@10 2745
rlm@10 2746 (defn numerator
rlm@10 2747 "Returns the numerator part of a Ratio."
rlm@10 2748 {:tag BigInteger
rlm@10 2749 :added "1.2"}
rlm@10 2750 [r]
rlm@10 2751 (.numerator ^clojure.lang.Ratio r))
rlm@10 2752
rlm@10 2753 (defn denominator
rlm@10 2754 "Returns the denominator part of a Ratio."
rlm@10 2755 {:tag BigInteger
rlm@10 2756 :added "1.2"}
rlm@10 2757 [r]
rlm@10 2758 (.denominator ^clojure.lang.Ratio r))
rlm@10 2759
rlm@10 2760 (defn decimal?
rlm@10 2761 "Returns true if n is a BigDecimal"
rlm@10 2762 {:added "1.0"}
rlm@10 2763 [n] (instance? BigDecimal n))
rlm@10 2764
rlm@10 2765 (defn float?
rlm@10 2766 "Returns true if n is a floating point number"
rlm@10 2767 {:added "1.0"}
rlm@10 2768 [n]
rlm@10 2769 (or (instance? Double n)
rlm@10 2770 (instance? Float n)))
rlm@10 2771
rlm@10 2772 (defn rational? [n]
rlm@10 2773 "Returns true if n is a rational number"
rlm@10 2774 {:added "1.0"}
rlm@10 2775 (or (integer? n) (ratio? n) (decimal? n)))
rlm@10 2776
rlm@10 2777 (defn bigint
rlm@10 2778 "Coerce to BigInteger"
rlm@10 2779 {:tag BigInteger
rlm@10 2780 :added "1.0"}
rlm@10 2781 [x] (cond
rlm@10 2782 (instance? BigInteger x) x
rlm@10 2783 (decimal? x) (.toBigInteger ^BigDecimal x)
rlm@10 2784 (ratio? x) (.bigIntegerValue ^clojure.lang.Ratio x)
rlm@10 2785 (number? x) (BigInteger/valueOf (long x))
rlm@10 2786 :else (BigInteger. x)))
rlm@10 2787
rlm@10 2788 (defn bigdec
rlm@10 2789 "Coerce to BigDecimal"
rlm@10 2790 {:tag BigDecimal
rlm@10 2791 :added "1.0"}
rlm@10 2792 [x] (cond
rlm@10 2793 (decimal? x) x
rlm@10 2794 (float? x) (. BigDecimal valueOf (double x))
rlm@10 2795 (ratio? x) (/ (BigDecimal. (.numerator x)) (.denominator x))
rlm@10 2796 (instance? BigInteger x) (BigDecimal. ^BigInteger x)
rlm@10 2797 (number? x) (BigDecimal/valueOf (long x))
rlm@10 2798 :else (BigDecimal. x)))
rlm@10 2799
rlm@10 2800 (def ^{:private true} print-initialized false)
rlm@10 2801
rlm@10 2802 (defmulti print-method (fn [x writer] (type x)))
rlm@10 2803 (defmulti print-dup (fn [x writer] (class x)))
rlm@10 2804
rlm@10 2805 (defn pr-on
rlm@10 2806 {:private true}
rlm@10 2807 [x w]
rlm@10 2808 (if *print-dup*
rlm@10 2809 (print-dup x w)
rlm@10 2810 (print-method x w))
rlm@10 2811 nil)
rlm@10 2812
rlm@10 2813 (defn pr
rlm@10 2814 "Prints the object(s) to the output stream that is the current value
rlm@10 2815 of *out*. Prints the object(s), separated by spaces if there is
rlm@10 2816 more than one. By default, pr and prn print in a way that objects
rlm@10 2817 can be read by the reader"
rlm@10 2818 {:dynamic true
rlm@10 2819 :added "1.0"}
rlm@10 2820 ([] nil)
rlm@10 2821 ([x]
rlm@10 2822 (pr-on x *out*))
rlm@10 2823 ([x & more]
rlm@10 2824 (pr x)
rlm@10 2825 (. *out* (append \space))
rlm@10 2826 (if-let [nmore (next more)]
rlm@10 2827 (recur (first more) nmore)
rlm@10 2828 (apply pr more))))
rlm@10 2829
rlm@10 2830 (defn newline
rlm@10 2831 "Writes a newline to the output stream that is the current value of
rlm@10 2832 *out*"
rlm@10 2833 {:added "1.0"}
rlm@10 2834 []
rlm@10 2835 (. *out* (append \newline))
rlm@10 2836 nil)
rlm@10 2837
rlm@10 2838 (defn flush
rlm@10 2839 "Flushes the output stream that is the current value of
rlm@10 2840 *out*"
rlm@10 2841 {:added "1.0"}
rlm@10 2842 []
rlm@10 2843 (. *out* (flush))
rlm@10 2844 nil)
rlm@10 2845
rlm@10 2846 (defn prn
rlm@10 2847 "Same as pr followed by (newline). Observes *flush-on-newline*"
rlm@10 2848 {:added "1.0"}
rlm@10 2849 [& more]
rlm@10 2850 (apply pr more)
rlm@10 2851 (newline)
rlm@10 2852 (when *flush-on-newline*
rlm@10 2853 (flush)))
rlm@10 2854
rlm@10 2855 (defn print
rlm@10 2856 "Prints the object(s) to the output stream that is the current value
rlm@10 2857 of *out*. print and println produce output for human consumption."
rlm@10 2858 {:added "1.0"}
rlm@10 2859 [& more]
rlm@10 2860 (binding [*print-readably* nil]
rlm@10 2861 (apply pr more)))
rlm@10 2862
rlm@10 2863 (defn println
rlm@10 2864 "Same as print followed by (newline)"
rlm@10 2865 {:added "1.0"}
rlm@10 2866 [& more]
rlm@10 2867 (binding [*print-readably* nil]
rlm@10 2868 (apply prn more)))
rlm@10 2869
rlm@10 2870 (defn read
rlm@10 2871 "Reads the next object from stream, which must be an instance of
rlm@10 2872 java.io.PushbackReader or some derivee. stream defaults to the
rlm@10 2873 current value of *in* ."
rlm@10 2874 {:added "1.0"}
rlm@10 2875 ([]
rlm@10 2876 (read *in*))
rlm@10 2877 ([stream]
rlm@10 2878 (read stream true nil))
rlm@10 2879 ([stream eof-error? eof-value]
rlm@10 2880 (read stream eof-error? eof-value false))
rlm@10 2881 ([stream eof-error? eof-value recursive?]
rlm@10 2882 (. clojure.lang.LispReader (read stream (boolean eof-error?) eof-value recursive?))))
rlm@10 2883
rlm@10 2884 (defn read-line
rlm@10 2885 "Reads the next line from stream that is the current value of *in* ."
rlm@10 2886 {:added "1.0"}
rlm@10 2887 []
rlm@10 2888 (if (instance? clojure.lang.LineNumberingPushbackReader *in*)
rlm@10 2889 (.readLine ^clojure.lang.LineNumberingPushbackReader *in*)
rlm@10 2890 (.readLine ^java.io.BufferedReader *in*)))
rlm@10 2891
rlm@10 2892 (defn read-string
rlm@10 2893 "Reads one object from the string s"
rlm@10 2894 {:added "1.0"}
rlm@10 2895 [s] (clojure.lang.RT/readString s))
rlm@10 2896
rlm@10 2897 (defn subvec
rlm@10 2898 "Returns a persistent vector of the items in vector from
rlm@10 2899 start (inclusive) to end (exclusive). If end is not supplied,
rlm@10 2900 defaults to (count vector). This operation is O(1) and very fast, as
rlm@10 2901 the resulting vector shares structure with the original and no
rlm@10 2902 trimming is done."
rlm@10 2903 {:added "1.0"}
rlm@10 2904 ([v start]
rlm@10 2905 (subvec v start (count v)))
rlm@10 2906 ([v start end]
rlm@10 2907 (. clojure.lang.RT (subvec v start end))))
rlm@10 2908
rlm@10 2909 (defmacro with-open
rlm@10 2910 "bindings => [name init ...]
rlm@10 2911
rlm@10 2912 Evaluates body in a try expression with names bound to the values
rlm@10 2913 of the inits, and a finally clause that calls (.close name) on each
rlm@10 2914 name in reverse order."
rlm@10 2915 {:added "1.0"}
rlm@10 2916 [bindings & body]
rlm@10 2917 (assert-args with-open
rlm@10 2918 (vector? bindings) "a vector for its binding"
rlm@10 2919 (even? (count bindings)) "an even number of forms in binding vector")
rlm@10 2920 (cond
rlm@10 2921 (= (count bindings) 0) `(do ~@body)
rlm@10 2922 (symbol? (bindings 0)) `(let ~(subvec bindings 0 2)
rlm@10 2923 (try
rlm@10 2924 (with-open ~(subvec bindings 2) ~@body)
rlm@10 2925 (finally
rlm@10 2926 (. ~(bindings 0) close))))
rlm@10 2927 :else (throw (IllegalArgumentException.
rlm@10 2928 "with-open only allows Symbols in bindings"))))
rlm@10 2929
rlm@10 2930 (defmacro doto
rlm@10 2931 "Evaluates x then calls all of the methods and functions with the
rlm@10 2932 value of x supplied at the front of the given arguments. The forms
rlm@10 2933 are evaluated in order. Returns x.
rlm@10 2934
rlm@10 2935 (doto (new java.util.HashMap) (.put \"a\" 1) (.put \"b\" 2))"
rlm@10 2936 {:added "1.0"}
rlm@10 2937 [x & forms]
rlm@10 2938 (let [gx (gensym)]
rlm@10 2939 `(let [~gx ~x]
rlm@10 2940 ~@(map (fn [f]
rlm@10 2941 (if (seq? f)
rlm@10 2942 `(~(first f) ~gx ~@(next f))
rlm@10 2943 `(~f ~gx)))
rlm@10 2944 forms)
rlm@10 2945 ~gx)))
rlm@10 2946
rlm@10 2947 (defmacro memfn
rlm@10 2948 "Expands into code that creates a fn that expects to be passed an
rlm@10 2949 object and any args and calls the named instance method on the
rlm@10 2950 object passing the args. Use when you want to treat a Java method as
rlm@10 2951 a first-class fn."
rlm@10 2952 {:added "1.0"}
rlm@10 2953 [name & args]
rlm@10 2954 `(fn [target# ~@args]
rlm@10 2955 (. target# (~name ~@args))))
rlm@10 2956
rlm@10 2957 (defmacro time
rlm@10 2958 "Evaluates expr and prints the time it took. Returns the value of
rlm@10 2959 expr."
rlm@10 2960 {:added "1.0"}
rlm@10 2961 [expr]
rlm@10 2962 `(let [start# (. System (nanoTime))
rlm@10 2963 ret# ~expr]
rlm@10 2964 (prn (str "Elapsed time: " (/ (double (- (. System (nanoTime)) start#)) 1000000.0) " msecs"))
rlm@10 2965 ret#))
rlm@10 2966
rlm@10 2967
rlm@10 2968
rlm@10 2969 (import '(java.lang.reflect Array))
rlm@10 2970
rlm@10 2971 (defn alength
rlm@10 2972 "Returns the length of the Java array. Works on arrays of all
rlm@10 2973 types."
rlm@10 2974 {:inline (fn [a] `(. clojure.lang.RT (alength ~a)))
rlm@10 2975 :added "1.0"}
rlm@10 2976 [array] (. clojure.lang.RT (alength array)))
rlm@10 2977
rlm@10 2978 (defn aclone
rlm@10 2979 "Returns a clone of the Java array. Works on arrays of known
rlm@10 2980 types."
rlm@10 2981 {:inline (fn [a] `(. clojure.lang.RT (aclone ~a)))
rlm@10 2982 :added "1.0"}
rlm@10 2983 [array] (. clojure.lang.RT (aclone array)))
rlm@10 2984
rlm@10 2985 (defn aget
rlm@10 2986 "Returns the value at the index/indices. Works on Java arrays of all
rlm@10 2987 types."
rlm@10 2988 {:inline (fn [a i] `(. clojure.lang.RT (aget ~a (int ~i))))
rlm@10 2989 :inline-arities #{2}
rlm@10 2990 :added "1.0"}
rlm@10 2991 ([array idx]
rlm@10 2992 (clojure.lang.Reflector/prepRet (. Array (get array idx))))
rlm@10 2993 ([array idx & idxs]
rlm@10 2994 (apply aget (aget array idx) idxs)))
rlm@10 2995
rlm@10 2996 (defn aset
rlm@10 2997 "Sets the value at the index/indices. Works on Java arrays of
rlm@10 2998 reference types. Returns val."
rlm@10 2999 {:inline (fn [a i v] `(. clojure.lang.RT (aset ~a (int ~i) ~v)))
rlm@10 3000 :inline-arities #{3}
rlm@10 3001 :added "1.0"}
rlm@10 3002 ([array idx val]
rlm@10 3003 (. Array (set array idx val))
rlm@10 3004 val)
rlm@10 3005 ([array idx idx2 & idxv]
rlm@10 3006 (apply aset (aget array idx) idx2 idxv)))
rlm@10 3007
rlm@10 3008 (defmacro
rlm@10 3009 ^{:private true}
rlm@10 3010 def-aset [name method coerce]
rlm@10 3011 `(defn ~name
rlm@10 3012 {:arglists '([~'array ~'idx ~'val] [~'array ~'idx ~'idx2 & ~'idxv])}
rlm@10 3013 ([array# idx# val#]
rlm@10 3014 (. Array (~method array# idx# (~coerce val#)))
rlm@10 3015 val#)
rlm@10 3016 ([array# idx# idx2# & idxv#]
rlm@10 3017 (apply ~name (aget array# idx#) idx2# idxv#))))
rlm@10 3018
rlm@10 3019 (def-aset
rlm@10 3020 ^{:doc "Sets the value at the index/indices. Works on arrays of int. Returns val."
rlm@10 3021 :added "1.0"}
rlm@10 3022 aset-int setInt int)
rlm@10 3023
rlm@10 3024 (def-aset
rlm@10 3025 ^{:doc "Sets the value at the index/indices. Works on arrays of long. Returns val."
rlm@10 3026 :added "1.0"}
rlm@10 3027 aset-long setLong long)
rlm@10 3028
rlm@10 3029 (def-aset
rlm@10 3030 ^{:doc "Sets the value at the index/indices. Works on arrays of boolean. Returns val."
rlm@10 3031 :added "1.0"}
rlm@10 3032 aset-boolean setBoolean boolean)
rlm@10 3033
rlm@10 3034 (def-aset
rlm@10 3035 ^{:doc "Sets the value at the index/indices. Works on arrays of float. Returns val."
rlm@10 3036 :added "1.0"}
rlm@10 3037 aset-float setFloat float)
rlm@10 3038
rlm@10 3039 (def-aset
rlm@10 3040 ^{:doc "Sets the value at the index/indices. Works on arrays of double. Returns val."
rlm@10 3041 :added "1.0"}
rlm@10 3042 aset-double setDouble double)
rlm@10 3043
rlm@10 3044 (def-aset
rlm@10 3045 ^{:doc "Sets the value at the index/indices. Works on arrays of short. Returns val."
rlm@10 3046 :added "1.0"}
rlm@10 3047 aset-short setShort short)
rlm@10 3048
rlm@10 3049 (def-aset
rlm@10 3050 ^{:doc "Sets the value at the index/indices. Works on arrays of byte. Returns val."
rlm@10 3051 :added "1.0"}
rlm@10 3052 aset-byte setByte byte)
rlm@10 3053
rlm@10 3054 (def-aset
rlm@10 3055 ^{:doc "Sets the value at the index/indices. Works on arrays of char. Returns val."
rlm@10 3056 :added "1.0"}
rlm@10 3057 aset-char setChar char)
rlm@10 3058
rlm@10 3059 (defn make-array
rlm@10 3060 "Creates and returns an array of instances of the specified class of
rlm@10 3061 the specified dimension(s). Note that a class object is required.
rlm@10 3062 Class objects can be obtained by using their imported or
rlm@10 3063 fully-qualified name. Class objects for the primitive types can be
rlm@10 3064 obtained using, e.g., Integer/TYPE."
rlm@10 3065 {:added "1.0"}
rlm@10 3066 ([^Class type len]
rlm@10 3067 (. Array (newInstance type (int len))))
rlm@10 3068 ([^Class type dim & more-dims]
rlm@10 3069 (let [dims (cons dim more-dims)
rlm@10 3070 ^"[I" dimarray (make-array (. Integer TYPE) (count dims))]
rlm@10 3071 (dotimes [i (alength dimarray)]
rlm@10 3072 (aset-int dimarray i (nth dims i)))
rlm@10 3073 (. Array (newInstance type dimarray)))))
rlm@10 3074
rlm@10 3075 (defn to-array-2d
rlm@10 3076 "Returns a (potentially-ragged) 2-dimensional array of Objects
rlm@10 3077 containing the contents of coll, which can be any Collection of any
rlm@10 3078 Collection."
rlm@10 3079 {:tag "[[Ljava.lang.Object;"
rlm@10 3080 :added "1.0"}
rlm@10 3081 [^java.util.Collection coll]
rlm@10 3082 (let [ret (make-array (. Class (forName "[Ljava.lang.Object;")) (. coll (size)))]
rlm@10 3083 (loop [i 0 xs (seq coll)]
rlm@10 3084 (when xs
rlm@10 3085 (aset ret i (to-array (first xs)))
rlm@10 3086 (recur (inc i) (next xs))))
rlm@10 3087 ret))
rlm@10 3088
rlm@10 3089 (defn macroexpand-1
rlm@10 3090 "If form represents a macro form, returns its expansion,
rlm@10 3091 else returns form."
rlm@10 3092 {:added "1.0"}
rlm@10 3093 [form]
rlm@10 3094 (. clojure.lang.Compiler (macroexpand1 form)))
rlm@10 3095
rlm@10 3096 (defn macroexpand
rlm@10 3097 "Repeatedly calls macroexpand-1 on form until it no longer
rlm@10 3098 represents a macro form, then returns it. Note neither
rlm@10 3099 macroexpand-1 nor macroexpand expand macros in subforms."
rlm@10 3100 {:added "1.0"}
rlm@10 3101 [form]
rlm@10 3102 (let [ex (macroexpand-1 form)]
rlm@10 3103 (if (identical? ex form)
rlm@10 3104 form
rlm@10 3105 (macroexpand ex))))
rlm@10 3106
rlm@10 3107 (defn create-struct
rlm@10 3108 "Returns a structure basis object."
rlm@10 3109 {:added "1.0"}
rlm@10 3110 [& keys]
rlm@10 3111 (. clojure.lang.PersistentStructMap (createSlotMap keys)))
rlm@10 3112
rlm@10 3113 (defmacro defstruct
rlm@10 3114 "Same as (def name (create-struct keys...))"
rlm@10 3115 {:added "1.0"}
rlm@10 3116 [name & keys]
rlm@10 3117 `(def ~name (create-struct ~@keys)))
rlm@10 3118
rlm@10 3119 (defn struct-map
rlm@10 3120 "Returns a new structmap instance with the keys of the
rlm@10 3121 structure-basis. keyvals may contain all, some or none of the basis
rlm@10 3122 keys - where values are not supplied they will default to nil.
rlm@10 3123 keyvals can also contain keys not in the basis."
rlm@10 3124 {:added "1.0"}
rlm@10 3125 [s & inits]
rlm@10 3126 (. clojure.lang.PersistentStructMap (create s inits)))
rlm@10 3127
rlm@10 3128 (defn struct
rlm@10 3129 "Returns a new structmap instance with the keys of the
rlm@10 3130 structure-basis. vals must be supplied for basis keys in order -
rlm@10 3131 where values are not supplied they will default to nil."
rlm@10 3132 {:added "1.0"}
rlm@10 3133 [s & vals]
rlm@10 3134 (. clojure.lang.PersistentStructMap (construct s vals)))
rlm@10 3135
rlm@10 3136 (defn accessor
rlm@10 3137 "Returns a fn that, given an instance of a structmap with the basis,
rlm@10 3138 returns the value at the key. The key must be in the basis. The
rlm@10 3139 returned function should be (slightly) more efficient than using
rlm@10 3140 get, but such use of accessors should be limited to known
rlm@10 3141 performance-critical areas."
rlm@10 3142 {:added "1.0"}
rlm@10 3143 [s key]
rlm@10 3144 (. clojure.lang.PersistentStructMap (getAccessor s key)))
rlm@10 3145
rlm@10 3146 (defn load-reader
rlm@10 3147 "Sequentially read and evaluate the set of forms contained in the
rlm@10 3148 stream/file"
rlm@10 3149 {:added "1.0"}
rlm@10 3150 [rdr] (. clojure.lang.Compiler (load rdr)))
rlm@10 3151
rlm@10 3152 (defn load-string
rlm@10 3153 "Sequentially read and evaluate the set of forms contained in the
rlm@10 3154 string"
rlm@10 3155 {:added "1.0"}
rlm@10 3156 [s]
rlm@10 3157 (let [rdr (-> (java.io.StringReader. s)
rlm@10 3158 (clojure.lang.LineNumberingPushbackReader.))]
rlm@10 3159 (load-reader rdr)))
rlm@10 3160
rlm@10 3161 (defn set
rlm@10 3162 "Returns a set of the distinct elements of coll."
rlm@10 3163 {:added "1.0"}
rlm@10 3164 [coll] (clojure.lang.PersistentHashSet/create ^clojure.lang.ISeq (seq coll)))
rlm@10 3165
rlm@10 3166 (defn ^{:private true}
rlm@10 3167 filter-key [keyfn pred amap]
rlm@10 3168 (loop [ret {} es (seq amap)]
rlm@10 3169 (if es
rlm@10 3170 (if (pred (keyfn (first es)))
rlm@10 3171 (recur (assoc ret (key (first es)) (val (first es))) (next es))
rlm@10 3172 (recur ret (next es)))
rlm@10 3173 ret)))
rlm@10 3174
rlm@10 3175 (defn find-ns
rlm@10 3176 "Returns the namespace named by the symbol or nil if it doesn't exist."
rlm@10 3177 {:added "1.0"}
rlm@10 3178 [sym] (clojure.lang.Namespace/find sym))
rlm@10 3179
rlm@10 3180 (defn create-ns
rlm@10 3181 "Create a new namespace named by the symbol if one doesn't already
rlm@10 3182 exist, returns it or the already-existing namespace of the same
rlm@10 3183 name."
rlm@10 3184 {:added "1.0"}
rlm@10 3185 [sym] (clojure.lang.Namespace/findOrCreate sym))
rlm@10 3186
rlm@10 3187 (defn remove-ns
rlm@10 3188 "Removes the namespace named by the symbol. Use with caution.
rlm@10 3189 Cannot be used to remove the clojure namespace."
rlm@10 3190 {:added "1.0"}
rlm@10 3191 [sym] (clojure.lang.Namespace/remove sym))
rlm@10 3192
rlm@10 3193 (defn all-ns
rlm@10 3194 "Returns a sequence of all namespaces."
rlm@10 3195 {:added "1.0"}
rlm@10 3196 [] (clojure.lang.Namespace/all))
rlm@10 3197
rlm@10 3198 (defn ^clojure.lang.Namespace the-ns
rlm@10 3199 "If passed a namespace, returns it. Else, when passed a symbol,
rlm@10 3200 returns the namespace named by it, throwing an exception if not
rlm@10 3201 found."
rlm@10 3202 {:added "1.0"}
rlm@10 3203 [x]
rlm@10 3204 (if (instance? clojure.lang.Namespace x)
rlm@10 3205 x
rlm@10 3206 (or (find-ns x) (throw (Exception. (str "No namespace: " x " found"))))))
rlm@10 3207
rlm@10 3208 (defn ns-name
rlm@10 3209 "Returns the name of the namespace, a symbol."
rlm@10 3210 {:added "1.0"}
rlm@10 3211 [ns]
rlm@10 3212 (.getName (the-ns ns)))
rlm@10 3213
rlm@10 3214 (defn ns-map
rlm@10 3215 "Returns a map of all the mappings for the namespace."
rlm@10 3216 {:added "1.0"}
rlm@10 3217 [ns]
rlm@10 3218 (.getMappings (the-ns ns)))
rlm@10 3219
rlm@10 3220 (defn ns-unmap
rlm@10 3221 "Removes the mappings for the symbol from the namespace."
rlm@10 3222 {:added "1.0"}
rlm@10 3223 [ns sym]
rlm@10 3224 (.unmap (the-ns ns) sym))
rlm@10 3225
rlm@10 3226 ;(defn export [syms]
rlm@10 3227 ; (doseq [sym syms]
rlm@10 3228 ; (.. *ns* (intern sym) (setExported true))))
rlm@10 3229
rlm@10 3230 (defn ns-publics
rlm@10 3231 "Returns a map of the public intern mappings for the namespace."
rlm@10 3232 {:added "1.0"}
rlm@10 3233 [ns]
rlm@10 3234 (let [ns (the-ns ns)]
rlm@10 3235 (filter-key val (fn [^clojure.lang.Var v] (and (instance? clojure.lang.Var v)
rlm@10 3236 (= ns (.ns v))
rlm@10 3237 (.isPublic v)))
rlm@10 3238 (ns-map ns))))
rlm@10 3239
rlm@10 3240 (defn ns-imports
rlm@10 3241 "Returns a map of the import mappings for the namespace."
rlm@10 3242 {:added "1.0"}
rlm@10 3243 [ns]
rlm@10 3244 (filter-key val (partial instance? Class) (ns-map ns)))
rlm@10 3245
rlm@10 3246 (defn ns-interns
rlm@10 3247 "Returns a map of the intern mappings for the namespace."
rlm@10 3248 {:added "1.0"}
rlm@10 3249 [ns]
rlm@10 3250 (let [ns (the-ns ns)]
rlm@10 3251 (filter-key val (fn [^clojure.lang.Var v] (and (instance? clojure.lang.Var v)
rlm@10 3252 (= ns (.ns v))))
rlm@10 3253 (ns-map ns))))
rlm@10 3254
rlm@10 3255 (defn refer
rlm@10 3256 "refers to all public vars of ns, subject to filters.
rlm@10 3257 filters can include at most one each of:
rlm@10 3258
rlm@10 3259 :exclude list-of-symbols
rlm@10 3260 :only list-of-symbols
rlm@10 3261 :rename map-of-fromsymbol-tosymbol
rlm@10 3262
rlm@10 3263 For each public interned var in the namespace named by the symbol,
rlm@10 3264 adds a mapping from the name of the var to the var to the current
rlm@10 3265 namespace. Throws an exception if name is already mapped to
rlm@10 3266 something else in the current namespace. Filters can be used to
rlm@10 3267 select a subset, via inclusion or exclusion, or to provide a mapping
rlm@10 3268 to a symbol different from the var's name, in order to prevent
rlm@10 3269 clashes. Use :use in the ns macro in preference to calling this directly."
rlm@10 3270 {:added "1.0"}
rlm@10 3271 [ns-sym & filters]
rlm@10 3272 (let [ns (or (find-ns ns-sym) (throw (new Exception (str "No namespace: " ns-sym))))
rlm@10 3273 fs (apply hash-map filters)
rlm@10 3274 nspublics (ns-publics ns)
rlm@10 3275 rename (or (:rename fs) {})
rlm@10 3276 exclude (set (:exclude fs))
rlm@10 3277 to-do (or (:only fs) (keys nspublics))]
rlm@10 3278 (doseq [sym to-do]
rlm@10 3279 (when-not (exclude sym)
rlm@10 3280 (let [v (nspublics sym)]
rlm@10 3281 (when-not v
rlm@10 3282 (throw (new java.lang.IllegalAccessError
rlm@10 3283 (if (get (ns-interns ns) sym)
rlm@10 3284 (str sym " is not public")
rlm@10 3285 (str sym " does not exist")))))
rlm@10 3286 (. *ns* (refer (or (rename sym) sym) v)))))))
rlm@10 3287
rlm@10 3288 (defn ns-refers
rlm@10 3289 "Returns a map of the refer mappings for the namespace."
rlm@10 3290 {:added "1.0"}
rlm@10 3291 [ns]
rlm@10 3292 (let [ns (the-ns ns)]
rlm@10 3293 (filter-key val (fn [^clojure.lang.Var v] (and (instance? clojure.lang.Var v)
rlm@10 3294 (not= ns (.ns v))))
rlm@10 3295 (ns-map ns))))
rlm@10 3296
rlm@10 3297 (defn alias
rlm@10 3298 "Add an alias in the current namespace to another
rlm@10 3299 namespace. Arguments are two symbols: the alias to be used, and
rlm@10 3300 the symbolic name of the target namespace. Use :as in the ns macro in preference
rlm@10 3301 to calling this directly."
rlm@10 3302 {:added "1.0"}
rlm@10 3303 [alias namespace-sym]
rlm@10 3304 (.addAlias *ns* alias (find-ns namespace-sym)))
rlm@10 3305
rlm@10 3306 (defn ns-aliases
rlm@10 3307 "Returns a map of the aliases for the namespace."
rlm@10 3308 {:added "1.0"}
rlm@10 3309 [ns]
rlm@10 3310 (.getAliases (the-ns ns)))
rlm@10 3311
rlm@10 3312 (defn ns-unalias
rlm@10 3313 "Removes the alias for the symbol from the namespace."
rlm@10 3314 {:added "1.0"}
rlm@10 3315 [ns sym]
rlm@10 3316 (.removeAlias (the-ns ns) sym))
rlm@10 3317
rlm@10 3318 (defn take-nth
rlm@10 3319 "Returns a lazy seq of every nth item in coll."
rlm@10 3320 {:added "1.0"}
rlm@10 3321 [n coll]
rlm@10 3322 (lazy-seq
rlm@10 3323 (when-let [s (seq coll)]
rlm@10 3324 (cons (first s) (take-nth n (drop n s))))))
rlm@10 3325
rlm@10 3326 (defn interleave
rlm@10 3327 "Returns a lazy seq of the first item in each coll, then the second etc."
rlm@10 3328 {:added "1.0"}
rlm@10 3329 ([c1 c2]
rlm@10 3330 (lazy-seq
rlm@10 3331 (let [s1 (seq c1) s2 (seq c2)]
rlm@10 3332 (when (and s1 s2)
rlm@10 3333 (cons (first s1) (cons (first s2)
rlm@10 3334 (interleave (rest s1) (rest s2))))))))
rlm@10 3335 ([c1 c2 & colls]
rlm@10 3336 (lazy-seq
rlm@10 3337 (let [ss (map seq (conj colls c2 c1))]
rlm@10 3338 (when (every? identity ss)
rlm@10 3339 (concat (map first ss) (apply interleave (map rest ss))))))))
rlm@10 3340
rlm@10 3341 (defn var-get
rlm@10 3342 "Gets the value in the var object"
rlm@10 3343 {:added "1.0"}
rlm@10 3344 [^clojure.lang.Var x] (. x (get)))
rlm@10 3345
rlm@10 3346 (defn var-set
rlm@10 3347 "Sets the value in the var object to val. The var must be
rlm@10 3348 thread-locally bound."
rlm@10 3349 {:added "1.0"}
rlm@10 3350 [^clojure.lang.Var x val] (. x (set val)))
rlm@10 3351
rlm@10 3352 (defmacro with-local-vars
rlm@10 3353 "varbinding=> symbol init-expr
rlm@10 3354
rlm@10 3355 Executes the exprs in a context in which the symbols are bound to
rlm@10 3356 vars with per-thread bindings to the init-exprs. The symbols refer
rlm@10 3357 to the var objects themselves, and must be accessed with var-get and
rlm@10 3358 var-set"
rlm@10 3359 {:added "1.0"}
rlm@10 3360 [name-vals-vec & body]
rlm@10 3361 (assert-args with-local-vars
rlm@10 3362 (vector? name-vals-vec) "a vector for its binding"
rlm@10 3363 (even? (count name-vals-vec)) "an even number of forms in binding vector")
rlm@10 3364 `(let [~@(interleave (take-nth 2 name-vals-vec)
rlm@10 3365 (repeat '(. clojure.lang.Var (create))))]
rlm@10 3366 (. clojure.lang.Var (pushThreadBindings (hash-map ~@name-vals-vec)))
rlm@10 3367 (try
rlm@10 3368 ~@body
rlm@10 3369 (finally (. clojure.lang.Var (popThreadBindings))))))
rlm@10 3370
rlm@10 3371 (defn ns-resolve
rlm@10 3372 "Returns the var or Class to which a symbol will be resolved in the
rlm@10 3373 namespace, else nil. Note that if the symbol is fully qualified,
rlm@10 3374 the var/Class to which it resolves need not be present in the
rlm@10 3375 namespace."
rlm@10 3376 {:added "1.0"}
rlm@10 3377 [ns sym]
rlm@10 3378 (clojure.lang.Compiler/maybeResolveIn (the-ns ns) sym))
rlm@10 3379
rlm@10 3380 (defn resolve
rlm@10 3381 "same as (ns-resolve *ns* symbol)"
rlm@10 3382 {:added "1.0"}
rlm@10 3383 [sym] (ns-resolve *ns* sym))
rlm@10 3384
rlm@10 3385 (defn array-map
rlm@10 3386 "Constructs an array-map."
rlm@10 3387 {:added "1.0"}
rlm@10 3388 ([] (. clojure.lang.PersistentArrayMap EMPTY))
rlm@10 3389 ([& keyvals] (clojure.lang.PersistentArrayMap/createWithCheck (to-array keyvals))))
rlm@10 3390
rlm@10 3391 (defn nthnext
rlm@10 3392 "Returns the nth next of coll, (seq coll) when n is 0."
rlm@10 3393 {:added "1.0"}
rlm@10 3394 [coll n]
rlm@10 3395 (loop [n n xs (seq coll)]
rlm@10 3396 (if (and xs (pos? n))
rlm@10 3397 (recur (dec n) (next xs))
rlm@10 3398 xs)))
rlm@10 3399
rlm@10 3400
rlm@10 3401 ;redefine let and loop with destructuring
rlm@10 3402 (defn destructure [bindings]
rlm@10 3403 (let [bents (partition 2 bindings)
rlm@10 3404 pb (fn pb [bvec b v]
rlm@10 3405 (let [pvec
rlm@10 3406 (fn [bvec b val]
rlm@10 3407 (let [gvec (gensym "vec__")]
rlm@10 3408 (loop [ret (-> bvec (conj gvec) (conj val))
rlm@10 3409 n 0
rlm@10 3410 bs b
rlm@10 3411 seen-rest? false]
rlm@10 3412 (if (seq bs)
rlm@10 3413 (let [firstb (first bs)]
rlm@10 3414 (cond
rlm@10 3415 (= firstb '&) (recur (pb ret (second bs) (list `nthnext gvec n))
rlm@10 3416 n
rlm@10 3417 (nnext bs)
rlm@10 3418 true)
rlm@10 3419 (= firstb :as) (pb ret (second bs) gvec)
rlm@10 3420 :else (if seen-rest?
rlm@10 3421 (throw (new Exception "Unsupported binding form, only :as can follow & parameter"))
rlm@10 3422 (recur (pb ret firstb (list `nth gvec n nil))
rlm@10 3423 (inc n)
rlm@10 3424 (next bs)
rlm@10 3425 seen-rest?))))
rlm@10 3426 ret))))
rlm@10 3427 pmap
rlm@10 3428 (fn [bvec b v]
rlm@10 3429 (let [gmap (or (:as b) (gensym "map__"))
rlm@10 3430 defaults (:or b)]
rlm@10 3431 (loop [ret (-> bvec (conj gmap) (conj v)
rlm@10 3432 (conj gmap) (conj `(if (seq? ~gmap) (apply hash-map ~gmap) ~gmap)))
rlm@10 3433 bes (reduce
rlm@10 3434 (fn [bes entry]
rlm@10 3435 (reduce #(assoc %1 %2 ((val entry) %2))
rlm@10 3436 (dissoc bes (key entry))
rlm@10 3437 ((key entry) bes)))
rlm@10 3438 (dissoc b :as :or)
rlm@10 3439 {:keys #(keyword (str %)), :strs str, :syms #(list `quote %)})]
rlm@10 3440 (if (seq bes)
rlm@10 3441 (let [bb (key (first bes))
rlm@10 3442 bk (val (first bes))
rlm@10 3443 has-default (contains? defaults bb)]
rlm@10 3444 (recur (pb ret bb (if has-default
rlm@10 3445 (list `get gmap bk (defaults bb))
rlm@10 3446 (list `get gmap bk)))
rlm@10 3447 (next bes)))
rlm@10 3448 ret))))]
rlm@10 3449 (cond
rlm@10 3450 (symbol? b) (-> bvec (conj b) (conj v))
rlm@10 3451 (vector? b) (pvec bvec b v)
rlm@10 3452 (map? b) (pmap bvec b v)
rlm@10 3453 :else (throw (new Exception (str "Unsupported binding form: " b))))))
rlm@10 3454 process-entry (fn [bvec b] (pb bvec (first b) (second b)))]
rlm@10 3455 (if (every? symbol? (map first bents))
rlm@10 3456 bindings
rlm@10 3457 (reduce process-entry [] bents))))
rlm@10 3458
rlm@10 3459 (defmacro let
rlm@10 3460 "Evaluates the exprs in a lexical context in which the symbols in
rlm@10 3461 the binding-forms are bound to their respective init-exprs or parts
rlm@10 3462 therein."
rlm@10 3463 {:added "1.0"}
rlm@10 3464 [bindings & body]
rlm@10 3465 (assert-args let
rlm@10 3466 (vector? bindings) "a vector for its binding"
rlm@10 3467 (even? (count bindings)) "an even number of forms in binding vector")
rlm@10 3468 `(let* ~(destructure bindings) ~@body))
rlm@10 3469
rlm@10 3470 (defn ^{:private true}
rlm@10 3471 maybe-destructured
rlm@10 3472 [params body]
rlm@10 3473 (if (every? symbol? params)
rlm@10 3474 (cons params body)
rlm@10 3475 (loop [params params
rlm@10 3476 new-params []
rlm@10 3477 lets []]
rlm@10 3478 (if params
rlm@10 3479 (if (symbol? (first params))
rlm@10 3480 (recur (next params) (conj new-params (first params)) lets)
rlm@10 3481 (let [gparam (gensym "p__")]
rlm@10 3482 (recur (next params) (conj new-params gparam)
rlm@10 3483 (-> lets (conj (first params)) (conj gparam)))))
rlm@10 3484 `(~new-params
rlm@10 3485 (let ~lets
rlm@10 3486 ~@body))))))
rlm@10 3487
rlm@10 3488 ;redefine fn with destructuring and pre/post conditions
rlm@10 3489 (defmacro fn
rlm@10 3490 "(fn name? [params* ] exprs*)
rlm@10 3491 (fn name? ([params* ] exprs*)+)
rlm@10 3492
rlm@10 3493 params => positional-params* , or positional-params* & next-param
rlm@10 3494 positional-param => binding-form
rlm@10 3495 next-param => binding-form
rlm@10 3496 name => symbol
rlm@10 3497
rlm@10 3498 Defines a function"
rlm@10 3499 {:added "1.0"}
rlm@10 3500 [& sigs]
rlm@10 3501 (let [name (if (symbol? (first sigs)) (first sigs) nil)
rlm@10 3502 sigs (if name (next sigs) sigs)
rlm@10 3503 sigs (if (vector? (first sigs)) (list sigs) sigs)
rlm@10 3504 psig (fn* [sig]
rlm@10 3505 (let [[params & body] sig
rlm@10 3506 conds (when (and (next body) (map? (first body)))
rlm@10 3507 (first body))
rlm@10 3508 body (if conds (next body) body)
rlm@10 3509 conds (or conds (meta params))
rlm@10 3510 pre (:pre conds)
rlm@10 3511 post (:post conds)
rlm@10 3512 body (if post
rlm@10 3513 `((let [~'% ~(if (< 1 (count body))
rlm@10 3514 `(do ~@body)
rlm@10 3515 (first body))]
rlm@10 3516 ~@(map (fn* [c] `(assert ~c)) post)
rlm@10 3517 ~'%))
rlm@10 3518 body)
rlm@10 3519 body (if pre
rlm@10 3520 (concat (map (fn* [c] `(assert ~c)) pre)
rlm@10 3521 body)
rlm@10 3522 body)]
rlm@10 3523 (maybe-destructured params body)))
rlm@10 3524 new-sigs (map psig sigs)]
rlm@10 3525 (with-meta
rlm@10 3526 (if name
rlm@10 3527 (list* 'fn* name new-sigs)
rlm@10 3528 (cons 'fn* new-sigs))
rlm@10 3529 (meta &form))))
rlm@10 3530
rlm@10 3531 (defmacro loop
rlm@10 3532 "Evaluates the exprs in a lexical context in which the symbols in
rlm@10 3533 the binding-forms are bound to their respective init-exprs or parts
rlm@10 3534 therein. Acts as a recur target."
rlm@10 3535 {:added "1.0"}
rlm@10 3536 [bindings & body]
rlm@10 3537 (assert-args loop
rlm@10 3538 (vector? bindings) "a vector for its binding"
rlm@10 3539 (even? (count bindings)) "an even number of forms in binding vector")
rlm@10 3540 (let [db (destructure bindings)]
rlm@10 3541 (if (= db bindings)
rlm@10 3542 `(loop* ~bindings ~@body)
rlm@10 3543 (let [vs (take-nth 2 (drop 1 bindings))
rlm@10 3544 bs (take-nth 2 bindings)
rlm@10 3545 gs (map (fn [b] (if (symbol? b) b (gensym))) bs)
rlm@10 3546 bfs (reduce (fn [ret [b v g]]
rlm@10 3547 (if (symbol? b)
rlm@10 3548 (conj ret g v)
rlm@10 3549 (conj ret g v b g)))
rlm@10 3550 [] (map vector bs vs gs))]
rlm@10 3551 `(let ~bfs
rlm@10 3552 (loop* ~(vec (interleave gs gs))
rlm@10 3553 (let ~(vec (interleave bs gs))
rlm@10 3554 ~@body)))))))
rlm@10 3555
rlm@10 3556 (defmacro when-first
rlm@10 3557 "bindings => x xs
rlm@10 3558
rlm@10 3559 Same as (when (seq xs) (let [x (first xs)] body))"
rlm@10 3560 {:added "1.0"}
rlm@10 3561 [bindings & body]
rlm@10 3562 (assert-args when-first
rlm@10 3563 (vector? bindings) "a vector for its binding"
rlm@10 3564 (= 2 (count bindings)) "exactly 2 forms in binding vector")
rlm@10 3565 (let [[x xs] bindings]
rlm@10 3566 `(when (seq ~xs)
rlm@10 3567 (let [~x (first ~xs)]
rlm@10 3568 ~@body))))
rlm@10 3569
rlm@10 3570 (defmacro lazy-cat
rlm@10 3571 "Expands to code which yields a lazy sequence of the concatenation
rlm@10 3572 of the supplied colls. Each coll expr is not evaluated until it is
rlm@10 3573 needed.
rlm@10 3574
rlm@10 3575 (lazy-cat xs ys zs) === (concat (lazy-seq xs) (lazy-seq ys) (lazy-seq zs))"
rlm@10 3576 {:added "1.0"}
rlm@10 3577 [& colls]
rlm@10 3578 `(concat ~@(map #(list `lazy-seq %) colls)))
rlm@10 3579
rlm@10 3580 (defmacro for
rlm@10 3581 "List comprehension. Takes a vector of one or more
rlm@10 3582 binding-form/collection-expr pairs, each followed by zero or more
rlm@10 3583 modifiers, and yields a lazy sequence of evaluations of expr.
rlm@10 3584 Collections are iterated in a nested fashion, rightmost fastest,
rlm@10 3585 and nested coll-exprs can refer to bindings created in prior
rlm@10 3586 binding-forms. Supported modifiers are: :let [binding-form expr ...],
rlm@10 3587 :while test, :when test.
rlm@10 3588
rlm@10 3589 (take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))"
rlm@10 3590 {:added "1.0"}
rlm@10 3591 [seq-exprs body-expr]
rlm@10 3592 (assert-args for
rlm@10 3593 (vector? seq-exprs) "a vector for its binding"
rlm@10 3594 (even? (count seq-exprs)) "an even number of forms in binding vector")
rlm@10 3595 (let [to-groups (fn [seq-exprs]
rlm@10 3596 (reduce (fn [groups [k v]]
rlm@10 3597 (if (keyword? k)
rlm@10 3598 (conj (pop groups) (conj (peek groups) [k v]))
rlm@10 3599 (conj groups [k v])))
rlm@10 3600 [] (partition 2 seq-exprs)))
rlm@10 3601 err (fn [& msg] (throw (IllegalArgumentException. ^String (apply str msg))))
rlm@10 3602 emit-bind (fn emit-bind [[[bind expr & mod-pairs]
rlm@10 3603 & [[_ next-expr] :as next-groups]]]
rlm@10 3604 (let [giter (gensym "iter__")
rlm@10 3605 gxs (gensym "s__")
rlm@10 3606 do-mod (fn do-mod [[[k v :as pair] & etc]]
rlm@10 3607 (cond
rlm@10 3608 (= k :let) `(let ~v ~(do-mod etc))
rlm@10 3609 (= k :while) `(when ~v ~(do-mod etc))
rlm@10 3610 (= k :when) `(if ~v
rlm@10 3611 ~(do-mod etc)
rlm@10 3612 (recur (rest ~gxs)))
rlm@10 3613 (keyword? k) (err "Invalid 'for' keyword " k)
rlm@10 3614 next-groups
rlm@10 3615 `(let [iterys# ~(emit-bind next-groups)
rlm@10 3616 fs# (seq (iterys# ~next-expr))]
rlm@10 3617 (if fs#
rlm@10 3618 (concat fs# (~giter (rest ~gxs)))
rlm@10 3619 (recur (rest ~gxs))))
rlm@10 3620 :else `(cons ~body-expr
rlm@10 3621 (~giter (rest ~gxs)))))]
rlm@10 3622 (if next-groups
rlm@10 3623 #_"not the inner-most loop"
rlm@10 3624 `(fn ~giter [~gxs]
rlm@10 3625 (lazy-seq
rlm@10 3626 (loop [~gxs ~gxs]
rlm@10 3627 (when-first [~bind ~gxs]
rlm@10 3628 ~(do-mod mod-pairs)))))
rlm@10 3629 #_"inner-most loop"
rlm@10 3630 (let [gi (gensym "i__")
rlm@10 3631 gb (gensym "b__")
rlm@10 3632 do-cmod (fn do-cmod [[[k v :as pair] & etc]]
rlm@10 3633 (cond
rlm@10 3634 (= k :let) `(let ~v ~(do-cmod etc))
rlm@10 3635 (= k :while) `(when ~v ~(do-cmod etc))
rlm@10 3636 (= k :when) `(if ~v
rlm@10 3637 ~(do-cmod etc)
rlm@10 3638 (recur
rlm@10 3639 (unchecked-inc ~gi)))
rlm@10 3640 (keyword? k)
rlm@10 3641 (err "Invalid 'for' keyword " k)
rlm@10 3642 :else
rlm@10 3643 `(do (chunk-append ~gb ~body-expr)
rlm@10 3644 (recur (unchecked-inc ~gi)))))]
rlm@10 3645 `(fn ~giter [~gxs]
rlm@10 3646 (lazy-seq
rlm@10 3647 (loop [~gxs ~gxs]
rlm@10 3648 (when-let [~gxs (seq ~gxs)]
rlm@10 3649 (if (chunked-seq? ~gxs)
rlm@10 3650 (let [c# (chunk-first ~gxs)
rlm@10 3651 size# (int (count c#))
rlm@10 3652 ~gb (chunk-buffer size#)]
rlm@10 3653 (if (loop [~gi (int 0)]
rlm@10 3654 (if (< ~gi size#)
rlm@10 3655 (let [~bind (.nth c# ~gi)]
rlm@10 3656 ~(do-cmod mod-pairs))
rlm@10 3657 true))
rlm@10 3658 (chunk-cons
rlm@10 3659 (chunk ~gb)
rlm@10 3660 (~giter (chunk-rest ~gxs)))
rlm@10 3661 (chunk-cons (chunk ~gb) nil)))
rlm@10 3662 (let [~bind (first ~gxs)]
rlm@10 3663 ~(do-mod mod-pairs)))))))))))]
rlm@10 3664 `(let [iter# ~(emit-bind (to-groups seq-exprs))]
rlm@10 3665 (iter# ~(second seq-exprs)))))
rlm@10 3666
rlm@10 3667 (defmacro comment
rlm@10 3668 "Ignores body, yields nil"
rlm@10 3669 {:added "1.0"}
rlm@10 3670 [& body])
rlm@10 3671
rlm@10 3672 (defmacro with-out-str
rlm@10 3673 "Evaluates exprs in a context in which *out* is bound to a fresh
rlm@10 3674 StringWriter. Returns the string created by any nested printing
rlm@10 3675 calls."
rlm@10 3676 {:added "1.0"}
rlm@10 3677 [& body]
rlm@10 3678 `(let [s# (new java.io.StringWriter)]
rlm@10 3679 (binding [*out* s#]
rlm@10 3680 ~@body
rlm@10 3681 (str s#))))
rlm@10 3682
rlm@10 3683 (defmacro with-in-str
rlm@10 3684 "Evaluates body in a context in which *in* is bound to a fresh
rlm@10 3685 StringReader initialized with the string s."
rlm@10 3686 {:added "1.0"}
rlm@10 3687 [s & body]
rlm@10 3688 `(with-open [s# (-> (java.io.StringReader. ~s) clojure.lang.LineNumberingPushbackReader.)]
rlm@10 3689 (binding [*in* s#]
rlm@10 3690 ~@body)))
rlm@10 3691
rlm@10 3692 (defn pr-str
rlm@10 3693 "pr to a string, returning it"
rlm@10 3694 {:tag String
rlm@10 3695 :added "1.0"}
rlm@10 3696 [& xs]
rlm@10 3697 (with-out-str
rlm@10 3698 (apply pr xs)))
rlm@10 3699
rlm@10 3700 (defn prn-str
rlm@10 3701 "prn to a string, returning it"
rlm@10 3702 {:tag String
rlm@10 3703 :added "1.0"}
rlm@10 3704 [& xs]
rlm@10 3705 (with-out-str
rlm@10 3706 (apply prn xs)))
rlm@10 3707
rlm@10 3708 (defn print-str
rlm@10 3709 "print to a string, returning it"
rlm@10 3710 {:tag String
rlm@10 3711 :added "1.0"}
rlm@10 3712 [& xs]
rlm@10 3713 (with-out-str
rlm@10 3714 (apply print xs)))
rlm@10 3715
rlm@10 3716 (defn println-str
rlm@10 3717 "println to a string, returning it"
rlm@10 3718 {:tag String
rlm@10 3719 :added "1.0"}
rlm@10 3720 [& xs]
rlm@10 3721 (with-out-str
rlm@10 3722 (apply println xs)))
rlm@10 3723
rlm@10 3724 (defmacro assert
rlm@10 3725 "Evaluates expr and throws an exception if it does not evaluate to
rlm@10 3726 logical true."
rlm@10 3727 {:added "1.0"}
rlm@10 3728 [x]
rlm@10 3729 (when *assert*
rlm@10 3730 `(when-not ~x
rlm@10 3731 (throw (new AssertionError (str "Assert failed: " (pr-str '~x)))))))
rlm@10 3732
rlm@10 3733 (defn test
rlm@10 3734 "test [v] finds fn at key :test in var metadata and calls it,
rlm@10 3735 presuming failure will throw exception"
rlm@10 3736 {:added "1.0"}
rlm@10 3737 [v]
rlm@10 3738 (let [f (:test (meta v))]
rlm@10 3739 (if f
rlm@10 3740 (do (f) :ok)
rlm@10 3741 :no-test)))
rlm@10 3742
rlm@10 3743 (defn re-pattern
rlm@10 3744 "Returns an instance of java.util.regex.Pattern, for use, e.g. in
rlm@10 3745 re-matcher."
rlm@10 3746 {:tag java.util.regex.Pattern
rlm@10 3747 :added "1.0"}
rlm@10 3748 [s] (if (instance? java.util.regex.Pattern s)
rlm@10 3749 s
rlm@10 3750 (. java.util.regex.Pattern (compile s))))
rlm@10 3751
rlm@10 3752 (defn re-matcher
rlm@10 3753 "Returns an instance of java.util.regex.Matcher, for use, e.g. in
rlm@10 3754 re-find."
rlm@10 3755 {:tag java.util.regex.Matcher
rlm@10 3756 :added "1.0"}
rlm@10 3757 [^java.util.regex.Pattern re s]
rlm@10 3758 (. re (matcher s)))
rlm@10 3759
rlm@10 3760 (defn re-groups
rlm@10 3761 "Returns the groups from the most recent match/find. If there are no
rlm@10 3762 nested groups, returns a string of the entire match. If there are
rlm@10 3763 nested groups, returns a vector of the groups, the first element
rlm@10 3764 being the entire match."
rlm@10 3765 {:added "1.0"}
rlm@10 3766 [^java.util.regex.Matcher m]
rlm@10 3767 (let [gc (. m (groupCount))]
rlm@10 3768 (if (zero? gc)
rlm@10 3769 (. m (group))
rlm@10 3770 (loop [ret [] c 0]
rlm@10 3771 (if (<= c gc)
rlm@10 3772 (recur (conj ret (. m (group c))) (inc c))
rlm@10 3773 ret)))))
rlm@10 3774
rlm@10 3775 (defn re-seq
rlm@10 3776 "Returns a lazy sequence of successive matches of pattern in string,
rlm@10 3777 using java.util.regex.Matcher.find(), each such match processed with
rlm@10 3778 re-groups."
rlm@10 3779 {:added "1.0"}
rlm@10 3780 [^java.util.regex.Pattern re s]
rlm@10 3781 (let [m (re-matcher re s)]
rlm@10 3782 ((fn step []
rlm@10 3783 (when (. m (find))
rlm@10 3784 (cons (re-groups m) (lazy-seq (step))))))))
rlm@10 3785
rlm@10 3786 (defn re-matches
rlm@10 3787 "Returns the match, if any, of string to pattern, using
rlm@10 3788 java.util.regex.Matcher.matches(). Uses re-groups to return the
rlm@10 3789 groups."
rlm@10 3790 {:added "1.0"}
rlm@10 3791 [^java.util.regex.Pattern re s]
rlm@10 3792 (let [m (re-matcher re s)]
rlm@10 3793 (when (. m (matches))
rlm@10 3794 (re-groups m))))
rlm@10 3795
rlm@10 3796
rlm@10 3797 (defn re-find
rlm@10 3798 "Returns the next regex match, if any, of string to pattern, using
rlm@10 3799 java.util.regex.Matcher.find(). Uses re-groups to return the
rlm@10 3800 groups."
rlm@10 3801 {:added "1.0"}
rlm@10 3802 ([^java.util.regex.Matcher m]
rlm@10 3803 (when (. m (find))
rlm@10 3804 (re-groups m)))
rlm@10 3805 ([^java.util.regex.Pattern re s]
rlm@10 3806 (let [m (re-matcher re s)]
rlm@10 3807 (re-find m))))
rlm@10 3808
rlm@10 3809 (defn rand
rlm@10 3810 "Returns a random floating point number between 0 (inclusive) and
rlm@10 3811 n (default 1) (exclusive)."
rlm@10 3812 {:added "1.0"}
rlm@10 3813 ([] (. Math (random)))
rlm@10 3814 ([n] (* n (rand))))
rlm@10 3815
rlm@10 3816 (defn rand-int
rlm@10 3817 "Returns a random integer between 0 (inclusive) and n (exclusive)."
rlm@10 3818 {:added "1.0"}
rlm@10 3819 [n] (int (rand n)))
rlm@10 3820
rlm@10 3821 (defmacro defn-
rlm@10 3822 "same as defn, yielding non-public def"
rlm@10 3823 {:added "1.0"}
rlm@10 3824 [name & decls]
rlm@10 3825 (list* `defn (with-meta name (assoc (meta name) :private true)) decls))
rlm@10 3826
rlm@10 3827 (defn print-doc [v]
rlm@10 3828 (println "-------------------------")
rlm@10 3829 (println (str (ns-name (:ns (meta v))) "/" (:name (meta v))))
rlm@10 3830 (prn (:arglists (meta v)))
rlm@10 3831 (when (:macro (meta v))
rlm@10 3832 (println "Macro"))
rlm@10 3833 (println " " (:doc (meta v))))
rlm@10 3834
rlm@10 3835 (defn find-doc
rlm@10 3836 "Prints documentation for any var whose documentation or name
rlm@10 3837 contains a match for re-string-or-pattern"
rlm@10 3838 {:added "1.0"}
rlm@10 3839 [re-string-or-pattern]
rlm@10 3840 (let [re (re-pattern re-string-or-pattern)]
rlm@10 3841 (doseq [ns (all-ns)
rlm@10 3842 v (sort-by (comp :name meta) (vals (ns-interns ns)))
rlm@10 3843 :when (and (:doc (meta v))
rlm@10 3844 (or (re-find (re-matcher re (:doc (meta v))))
rlm@10 3845 (re-find (re-matcher re (str (:name (meta v)))))))]
rlm@10 3846 (print-doc v))))
rlm@10 3847
rlm@10 3848 (defn special-form-anchor
rlm@10 3849 "Returns the anchor tag on http://clojure.org/special_forms for the
rlm@10 3850 special form x, or nil"
rlm@10 3851 {:added "1.0"}
rlm@10 3852 [x]
rlm@10 3853 (#{'. 'def 'do 'fn 'if 'let 'loop 'monitor-enter 'monitor-exit 'new
rlm@10 3854 'quote 'recur 'set! 'throw 'try 'var} x))
rlm@10 3855
rlm@10 3856 (defn syntax-symbol-anchor
rlm@10 3857 "Returns the anchor tag on http://clojure.org/special_forms for the
rlm@10 3858 special form that uses syntax symbol x, or nil"
rlm@10 3859 {:added "1.0"}
rlm@10 3860 [x]
rlm@10 3861 ({'& 'fn 'catch 'try 'finally 'try} x))
rlm@10 3862
rlm@10 3863 (defn print-special-doc
rlm@10 3864 [name type anchor]
rlm@10 3865 (println "-------------------------")
rlm@10 3866 (println name)
rlm@10 3867 (println type)
rlm@10 3868 (println (str " Please see http://clojure.org/special_forms#" anchor)))
rlm@10 3869
rlm@10 3870 (defn print-namespace-doc
rlm@10 3871 "Print the documentation string of a Namespace."
rlm@10 3872 {:added "1.0"}
rlm@10 3873 [nspace]
rlm@10 3874 (println "-------------------------")
rlm@10 3875 (println (str (ns-name nspace)))
rlm@10 3876 (println " " (:doc (meta nspace))))
rlm@10 3877
rlm@10 3878 (defmacro doc
rlm@10 3879 "Prints documentation for a var or special form given its name"
rlm@10 3880 {:added "1.0"}
rlm@10 3881 [name]
rlm@10 3882 (cond
rlm@10 3883 (special-form-anchor `~name)
rlm@10 3884 `(print-special-doc '~name "Special Form" (special-form-anchor '~name))
rlm@10 3885 (syntax-symbol-anchor `~name)
rlm@10 3886 `(print-special-doc '~name "Syntax Symbol" (syntax-symbol-anchor '~name))
rlm@10 3887 :else
rlm@10 3888 (let [nspace (find-ns name)]
rlm@10 3889 (if nspace
rlm@10 3890 `(print-namespace-doc ~nspace)
rlm@10 3891 `(print-doc (var ~name))))))
rlm@10 3892
rlm@10 3893 (defn tree-seq
rlm@10 3894 "Returns a lazy sequence of the nodes in a tree, via a depth-first walk.
rlm@10 3895 branch? must be a fn of one arg that returns true if passed a node
rlm@10 3896 that can have children (but may not). children must be a fn of one
rlm@10 3897 arg that returns a sequence of the children. Will only be called on
rlm@10 3898 nodes for which branch? returns true. Root is the root node of the
rlm@10 3899 tree."
rlm@10 3900 {:added "1.0"}
rlm@10 3901 [branch? children root]
rlm@10 3902 (let [walk (fn walk [node]
rlm@10 3903 (lazy-seq
rlm@10 3904 (cons node
rlm@10 3905 (when (branch? node)
rlm@10 3906 (mapcat walk (children node))))))]
rlm@10 3907 (walk root)))
rlm@10 3908
rlm@10 3909 (defn file-seq
rlm@10 3910 "A tree seq on java.io.Files"
rlm@10 3911 {:added "1.0"}
rlm@10 3912 [dir]
rlm@10 3913 (tree-seq
rlm@10 3914 (fn [^java.io.File f] (. f (isDirectory)))
rlm@10 3915 (fn [^java.io.File d] (seq (. d (listFiles))))
rlm@10 3916 dir))
rlm@10 3917
rlm@10 3918 (defn xml-seq
rlm@10 3919 "A tree seq on the xml elements as per xml/parse"
rlm@10 3920 {:added "1.0"}
rlm@10 3921 [root]
rlm@10 3922 (tree-seq
rlm@10 3923 (complement string?)
rlm@10 3924 (comp seq :content)
rlm@10 3925 root))
rlm@10 3926
rlm@10 3927 (defn special-symbol?
rlm@10 3928 "Returns true if s names a special form"
rlm@10 3929 {:added "1.0"}
rlm@10 3930 [s]
rlm@10 3931 (contains? (. clojure.lang.Compiler specials) s))
rlm@10 3932
rlm@10 3933 (defn var?
rlm@10 3934 "Returns true if v is of type clojure.lang.Var"
rlm@10 3935 {:added "1.0"}
rlm@10 3936 [v] (instance? clojure.lang.Var v))
rlm@10 3937
rlm@10 3938 (defn ^String subs
rlm@10 3939 "Returns the substring of s beginning at start inclusive, and ending
rlm@10 3940 at end (defaults to length of string), exclusive."
rlm@10 3941 {:added "1.0"}
rlm@10 3942 ([^String s start] (. s (substring start)))
rlm@10 3943 ([^String s start end] (. s (substring start end))))
rlm@10 3944
rlm@10 3945 (defn max-key
rlm@10 3946 "Returns the x for which (k x), a number, is greatest."
rlm@10 3947 {:added "1.0"}
rlm@10 3948 ([k x] x)
rlm@10 3949 ([k x y] (if (> (k x) (k y)) x y))
rlm@10 3950 ([k x y & more]
rlm@10 3951 (reduce #(max-key k %1 %2) (max-key k x y) more)))
rlm@10 3952
rlm@10 3953 (defn min-key
rlm@10 3954 "Returns the x for which (k x), a number, is least."
rlm@10 3955 {:added "1.0"}
rlm@10 3956 ([k x] x)
rlm@10 3957 ([k x y] (if (< (k x) (k y)) x y))
rlm@10 3958 ([k x y & more]
rlm@10 3959 (reduce #(min-key k %1 %2) (min-key k x y) more)))
rlm@10 3960
rlm@10 3961 (defn distinct
rlm@10 3962 "Returns a lazy sequence of the elements of coll with duplicates removed"
rlm@10 3963 {:added "1.0"}
rlm@10 3964 [coll]
rlm@10 3965 (let [step (fn step [xs seen]
rlm@10 3966 (lazy-seq
rlm@10 3967 ((fn [[f :as xs] seen]
rlm@10 3968 (when-let [s (seq xs)]
rlm@10 3969 (if (contains? seen f)
rlm@10 3970 (recur (rest s) seen)
rlm@10 3971 (cons f (step (rest s) (conj seen f))))))
rlm@10 3972 xs seen)))]
rlm@10 3973 (step coll #{})))
rlm@10 3974
rlm@10 3975
rlm@10 3976
rlm@10 3977 (defn replace
rlm@10 3978 "Given a map of replacement pairs and a vector/collection, returns a
rlm@10 3979 vector/seq with any elements = a key in smap replaced with the
rlm@10 3980 corresponding val in smap"
rlm@10 3981 {:added "1.0"}
rlm@10 3982 [smap coll]
rlm@10 3983 (if (vector? coll)
rlm@10 3984 (reduce (fn [v i]
rlm@10 3985 (if-let [e (find smap (nth v i))]
rlm@10 3986 (assoc v i (val e))
rlm@10 3987 v))
rlm@10 3988 coll (range (count coll)))
rlm@10 3989 (map #(if-let [e (find smap %)] (val e) %) coll)))
rlm@10 3990
rlm@10 3991 (defmacro dosync
rlm@10 3992 "Runs the exprs (in an implicit do) in a transaction that encompasses
rlm@10 3993 exprs and any nested calls. Starts a transaction if none is already
rlm@10 3994 running on this thread. Any uncaught exception will abort the
rlm@10 3995 transaction and flow out of dosync. The exprs may be run more than
rlm@10 3996 once, but any effects on Refs will be atomic."
rlm@10 3997 {:added "1.0"}
rlm@10 3998 [& exprs]
rlm@10 3999 `(sync nil ~@exprs))
rlm@10 4000
rlm@10 4001 (defmacro with-precision
rlm@10 4002 "Sets the precision and rounding mode to be used for BigDecimal operations.
rlm@10 4003
rlm@10 4004 Usage: (with-precision 10 (/ 1M 3))
rlm@10 4005 or: (with-precision 10 :rounding HALF_DOWN (/ 1M 3))
rlm@10 4006
rlm@10 4007 The rounding mode is one of CEILING, FLOOR, HALF_UP, HALF_DOWN,
rlm@10 4008 HALF_EVEN, UP, DOWN and UNNECESSARY; it defaults to HALF_UP."
rlm@10 4009 {:added "1.0"}
rlm@10 4010 [precision & exprs]
rlm@10 4011 (let [[body rm] (if (= (first exprs) :rounding)
rlm@10 4012 [(next (next exprs))
rlm@10 4013 `((. java.math.RoundingMode ~(second exprs)))]
rlm@10 4014 [exprs nil])]
rlm@10 4015 `(binding [*math-context* (java.math.MathContext. ~precision ~@rm)]
rlm@10 4016 ~@body)))
rlm@10 4017
rlm@10 4018 (defn mk-bound-fn
rlm@10 4019 {:private true}
rlm@10 4020 [^clojure.lang.Sorted sc test key]
rlm@10 4021 (fn [e]
rlm@10 4022 (test (.. sc comparator (compare (. sc entryKey e) key)) 0)))
rlm@10 4023
rlm@10 4024 (defn subseq
rlm@10 4025 "sc must be a sorted collection, test(s) one of <, <=, > or
rlm@10 4026 >=. Returns a seq of those entries with keys ek for
rlm@10 4027 which (test (.. sc comparator (compare ek key)) 0) is true"
rlm@10 4028 {:added "1.0"}
rlm@10 4029 ([^clojure.lang.Sorted sc test key]
rlm@10 4030 (let [include (mk-bound-fn sc test key)]
rlm@10 4031 (if (#{> >=} test)
rlm@10 4032 (when-let [[e :as s] (. sc seqFrom key true)]
rlm@10 4033 (if (include e) s (next s)))
rlm@10 4034 (take-while include (. sc seq true)))))
rlm@10 4035 ([^clojure.lang.Sorted sc start-test start-key end-test end-key]
rlm@10 4036 (when-let [[e :as s] (. sc seqFrom start-key true)]
rlm@10 4037 (take-while (mk-bound-fn sc end-test end-key)
rlm@10 4038 (if ((mk-bound-fn sc start-test start-key) e) s (next s))))))
rlm@10 4039
rlm@10 4040 (defn rsubseq
rlm@10 4041 "sc must be a sorted collection, test(s) one of <, <=, > or
rlm@10 4042 >=. Returns a reverse seq of those entries with keys ek for
rlm@10 4043 which (test (.. sc comparator (compare ek key)) 0) is true"
rlm@10 4044 {:added "1.0"}
rlm@10 4045 ([^clojure.lang.Sorted sc test key]
rlm@10 4046 (let [include (mk-bound-fn sc test key)]
rlm@10 4047 (if (#{< <=} test)
rlm@10 4048 (when-let [[e :as s] (. sc seqFrom key false)]
rlm@10 4049 (if (include e) s (next s)))
rlm@10 4050 (take-while include (. sc seq false)))))
rlm@10 4051 ([^clojure.lang.Sorted sc start-test start-key end-test end-key]
rlm@10 4052 (when-let [[e :as s] (. sc seqFrom end-key false)]
rlm@10 4053 (take-while (mk-bound-fn sc start-test start-key)
rlm@10 4054 (if ((mk-bound-fn sc end-test end-key) e) s (next s))))))
rlm@10 4055
rlm@10 4056 (defn repeatedly
rlm@10 4057 "Takes a function of no args, presumably with side effects, and
rlm@10 4058 returns an infinite (or length n if supplied) lazy sequence of calls
rlm@10 4059 to it"
rlm@10 4060 {:added "1.0"}
rlm@10 4061 ([f] (lazy-seq (cons (f) (repeatedly f))))
rlm@10 4062 ([n f] (take n (repeatedly f))))
rlm@10 4063
rlm@10 4064 (defn add-classpath
rlm@10 4065 "DEPRECATED
rlm@10 4066
rlm@10 4067 Adds the url (String or URL object) to the classpath per
rlm@10 4068 URLClassLoader.addURL"
rlm@10 4069 {:added "1.0"
rlm@10 4070 :deprecated "1.1"}
rlm@10 4071 [url]
rlm@10 4072 (println "WARNING: add-classpath is deprecated")
rlm@10 4073 (clojure.lang.RT/addURL url))
rlm@10 4074
rlm@10 4075
rlm@10 4076
rlm@10 4077 (defn hash
rlm@10 4078 "Returns the hash code of its argument"
rlm@10 4079 {:added "1.0"}
rlm@10 4080 [x] (. clojure.lang.Util (hash x)))
rlm@10 4081
rlm@10 4082 (defn interpose
rlm@10 4083 "Returns a lazy seq of the elements of coll separated by sep"
rlm@10 4084 {:added "1.0"}
rlm@10 4085 [sep coll] (drop 1 (interleave (repeat sep) coll)))
rlm@10 4086
rlm@10 4087 (defmacro definline
rlm@10 4088 "Experimental - like defmacro, except defines a named function whose
rlm@10 4089 body is the expansion, calls to which may be expanded inline as if
rlm@10 4090 it were a macro. Cannot be used with variadic (&) args."
rlm@10 4091 {:added "1.0"}
rlm@10 4092 [name & decl]
rlm@10 4093 (let [[pre-args [args expr]] (split-with (comp not vector?) decl)]
rlm@10 4094 `(do
rlm@10 4095 (defn ~name ~@pre-args ~args ~(apply (eval (list `fn args expr)) args))
rlm@10 4096 (alter-meta! (var ~name) assoc :inline (fn ~name ~args ~expr))
rlm@10 4097 (var ~name))))
rlm@10 4098
rlm@10 4099 (defn empty
rlm@10 4100 "Returns an empty collection of the same category as coll, or nil"
rlm@10 4101 {:added "1.0"}
rlm@10 4102 [coll]
rlm@10 4103 (when (instance? clojure.lang.IPersistentCollection coll)
rlm@10 4104 (.empty ^clojure.lang.IPersistentCollection coll)))
rlm@10 4105
rlm@10 4106 (defmacro amap
rlm@10 4107 "Maps an expression across an array a, using an index named idx, and
rlm@10 4108 return value named ret, initialized to a clone of a, then setting
rlm@10 4109 each element of ret to the evaluation of expr, returning the new
rlm@10 4110 array ret."
rlm@10 4111 {:added "1.0"}
rlm@10 4112 [a idx ret expr]
rlm@10 4113 `(let [a# ~a
rlm@10 4114 ~ret (aclone a#)]
rlm@10 4115 (loop [~idx (int 0)]
rlm@10 4116 (if (< ~idx (alength a#))
rlm@10 4117 (do
rlm@10 4118 (aset ~ret ~idx ~expr)
rlm@10 4119 (recur (unchecked-inc ~idx)))
rlm@10 4120 ~ret))))
rlm@10 4121
rlm@10 4122 (defmacro areduce
rlm@10 4123 "Reduces an expression across an array a, using an index named idx,
rlm@10 4124 and return value named ret, initialized to init, setting ret to the
rlm@10 4125 evaluation of expr at each step, returning ret."
rlm@10 4126 {:added "1.0"}
rlm@10 4127 [a idx ret init expr]
rlm@10 4128 `(let [a# ~a]
rlm@10 4129 (loop [~idx (int 0) ~ret ~init]
rlm@10 4130 (if (< ~idx (alength a#))
rlm@10 4131 (recur (unchecked-inc ~idx) ~expr)
rlm@10 4132 ~ret))))
rlm@10 4133
rlm@10 4134 (defn float-array
rlm@10 4135 "Creates an array of floats"
rlm@10 4136 {:inline (fn [& args] `(. clojure.lang.Numbers float_array ~@args))
rlm@10 4137 :inline-arities #{1 2}
rlm@10 4138 :added "1.0"}
rlm@10 4139 ([size-or-seq] (. clojure.lang.Numbers float_array size-or-seq))
rlm@10 4140 ([size init-val-or-seq] (. clojure.lang.Numbers float_array size init-val-or-seq)))
rlm@10 4141
rlm@10 4142 (defn boolean-array
rlm@10 4143 "Creates an array of booleans"
rlm@10 4144 {:inline (fn [& args] `(. clojure.lang.Numbers boolean_array ~@args))
rlm@10 4145 :inline-arities #{1 2}
rlm@10 4146 :added "1.1"}
rlm@10 4147 ([size-or-seq] (. clojure.lang.Numbers boolean_array size-or-seq))
rlm@10 4148 ([size init-val-or-seq] (. clojure.lang.Numbers boolean_array size init-val-or-seq)))
rlm@10 4149
rlm@10 4150 (defn byte-array
rlm@10 4151 "Creates an array of bytes"
rlm@10 4152 {:inline (fn [& args] `(. clojure.lang.Numbers byte_array ~@args))
rlm@10 4153 :inline-arities #{1 2}
rlm@10 4154 :added "1.1"}
rlm@10 4155 ([size-or-seq] (. clojure.lang.Numbers byte_array size-or-seq))
rlm@10 4156 ([size init-val-or-seq] (. clojure.lang.Numbers byte_array size init-val-or-seq)))
rlm@10 4157
rlm@10 4158 (defn char-array
rlm@10 4159 "Creates an array of chars"
rlm@10 4160 {:inline (fn [& args] `(. clojure.lang.Numbers char_array ~@args))
rlm@10 4161 :inline-arities #{1 2}
rlm@10 4162 :added "1.1"}
rlm@10 4163 ([size-or-seq] (. clojure.lang.Numbers char_array size-or-seq))
rlm@10 4164 ([size init-val-or-seq] (. clojure.lang.Numbers char_array size init-val-or-seq)))
rlm@10 4165
rlm@10 4166 (defn short-array
rlm@10 4167 "Creates an array of shorts"
rlm@10 4168 {:inline (fn [& args] `(. clojure.lang.Numbers short_array ~@args))
rlm@10 4169 :inline-arities #{1 2}
rlm@10 4170 :added "1.1"}
rlm@10 4171 ([size-or-seq] (. clojure.lang.Numbers short_array size-or-seq))
rlm@10 4172 ([size init-val-or-seq] (. clojure.lang.Numbers short_array size init-val-or-seq)))
rlm@10 4173
rlm@10 4174 (defn double-array
rlm@10 4175 "Creates an array of doubles"
rlm@10 4176 {:inline (fn [& args] `(. clojure.lang.Numbers double_array ~@args))
rlm@10 4177 :inline-arities #{1 2}
rlm@10 4178 :added "1.0"}
rlm@10 4179 ([size-or-seq] (. clojure.lang.Numbers double_array size-or-seq))
rlm@10 4180 ([size init-val-or-seq] (. clojure.lang.Numbers double_array size init-val-or-seq)))
rlm@10 4181
rlm@10 4182 (defn object-array
rlm@10 4183 "Creates an array of objects"
rlm@10 4184 {:inline (fn [arg] `(. clojure.lang.RT object_array ~arg))
rlm@10 4185 :inline-arities #{1}
rlm@10 4186 :added "1.2"}
rlm@10 4187 ([size-or-seq] (. clojure.lang.RT object_array size-or-seq)))
rlm@10 4188
rlm@10 4189 (defn int-array
rlm@10 4190 "Creates an array of ints"
rlm@10 4191 {:inline (fn [& args] `(. clojure.lang.Numbers int_array ~@args))
rlm@10 4192 :inline-arities #{1 2}
rlm@10 4193 :added "1.0"}
rlm@10 4194 ([size-or-seq] (. clojure.lang.Numbers int_array size-or-seq))
rlm@10 4195 ([size init-val-or-seq] (. clojure.lang.Numbers int_array size init-val-or-seq)))
rlm@10 4196
rlm@10 4197 (defn long-array
rlm@10 4198 "Creates an array of longs"
rlm@10 4199 {:inline (fn [& args] `(. clojure.lang.Numbers long_array ~@args))
rlm@10 4200 :inline-arities #{1 2}
rlm@10 4201 :added "1.0"}
rlm@10 4202 ([size-or-seq] (. clojure.lang.Numbers long_array size-or-seq))
rlm@10 4203 ([size init-val-or-seq] (. clojure.lang.Numbers long_array size init-val-or-seq)))
rlm@10 4204
rlm@10 4205 (definline booleans
rlm@10 4206 "Casts to boolean[]"
rlm@10 4207 {:added "1.1"}
rlm@10 4208 [xs] `(. clojure.lang.Numbers booleans ~xs))
rlm@10 4209
rlm@10 4210 (definline bytes
rlm@10 4211 "Casts to bytes[]"
rlm@10 4212 {:added "1.1"}
rlm@10 4213 [xs] `(. clojure.lang.Numbers bytes ~xs))
rlm@10 4214
rlm@10 4215 (definline chars
rlm@10 4216 "Casts to chars[]"
rlm@10 4217 {:added "1.1"}
rlm@10 4218 [xs] `(. clojure.lang.Numbers chars ~xs))
rlm@10 4219
rlm@10 4220 (definline shorts
rlm@10 4221 "Casts to shorts[]"
rlm@10 4222 {:added "1.1"}
rlm@10 4223 [xs] `(. clojure.lang.Numbers shorts ~xs))
rlm@10 4224
rlm@10 4225 (definline floats
rlm@10 4226 "Casts to float[]"
rlm@10 4227 {:added "1.0"}
rlm@10 4228 [xs] `(. clojure.lang.Numbers floats ~xs))
rlm@10 4229
rlm@10 4230 (definline ints
rlm@10 4231 "Casts to int[]"
rlm@10 4232 {:added "1.0"}
rlm@10 4233 [xs] `(. clojure.lang.Numbers ints ~xs))
rlm@10 4234
rlm@10 4235 (definline doubles
rlm@10 4236 "Casts to double[]"
rlm@10 4237 {:added "1.0"}
rlm@10 4238 [xs] `(. clojure.lang.Numbers doubles ~xs))
rlm@10 4239
rlm@10 4240 (definline longs
rlm@10 4241 "Casts to long[]"
rlm@10 4242 {:added "1.0"}
rlm@10 4243 [xs] `(. clojure.lang.Numbers longs ~xs))
rlm@10 4244
rlm@10 4245 (import '(java.util.concurrent BlockingQueue LinkedBlockingQueue))
rlm@10 4246
rlm@10 4247 (defn seque
rlm@10 4248 "Creates a queued seq on another (presumably lazy) seq s. The queued
rlm@10 4249 seq will produce a concrete seq in the background, and can get up to
rlm@10 4250 n items ahead of the consumer. n-or-q can be an integer n buffer
rlm@10 4251 size, or an instance of java.util.concurrent BlockingQueue. Note
rlm@10 4252 that reading from a seque can block if the reader gets ahead of the
rlm@10 4253 producer."
rlm@10 4254 {:added "1.0"}
rlm@10 4255 ([s] (seque 100 s))
rlm@10 4256 ([n-or-q s]
rlm@10 4257 (let [^BlockingQueue q (if (instance? BlockingQueue n-or-q)
rlm@10 4258 n-or-q
rlm@10 4259 (LinkedBlockingQueue. (int n-or-q)))
rlm@10 4260 NIL (Object.) ;nil sentinel since LBQ doesn't support nils
rlm@10 4261 agt (agent (seq s))
rlm@10 4262 fill (fn [s]
rlm@10 4263 (try
rlm@10 4264 (loop [[x & xs :as s] s]
rlm@10 4265 (if s
rlm@10 4266 (if (.offer q (if (nil? x) NIL x))
rlm@10 4267 (recur xs)
rlm@10 4268 s)
rlm@10 4269 (.put q q))) ; q itself is eos sentinel
rlm@10 4270 (catch Exception e
rlm@10 4271 (.put q q)
rlm@10 4272 (throw e))))
rlm@10 4273 drain (fn drain []
rlm@10 4274 (lazy-seq
rlm@10 4275 (let [x (.take q)]
rlm@10 4276 (if (identical? x q) ;q itself is eos sentinel
rlm@10 4277 (do @agt nil) ;touch agent just to propagate errors
rlm@10 4278 (do
rlm@10 4279 (send-off agt fill)
rlm@10 4280 (cons (if (identical? x NIL) nil x) (drain)))))))]
rlm@10 4281 (send-off agt fill)
rlm@10 4282 (drain))))
rlm@10 4283
rlm@10 4284 (defn class?
rlm@10 4285 "Returns true if x is an instance of Class"
rlm@10 4286 {:added "1.0"}
rlm@10 4287 [x] (instance? Class x))
rlm@10 4288
rlm@10 4289 (defn- is-annotation? [c]
rlm@10 4290 (and (class? c)
rlm@10 4291 (.isAssignableFrom java.lang.annotation.Annotation c)))
rlm@10 4292
rlm@10 4293 (defn- is-runtime-annotation? [^Class c]
rlm@10 4294 (boolean
rlm@10 4295 (and (is-annotation? c)
rlm@10 4296 (when-let [^java.lang.annotation.Retention r
rlm@10 4297 (.getAnnotation c java.lang.annotation.Retention)]
rlm@10 4298 (= (.value r) java.lang.annotation.RetentionPolicy/RUNTIME)))))
rlm@10 4299
rlm@10 4300 (defn- descriptor [^Class c] (clojure.asm.Type/getDescriptor c))
rlm@10 4301
rlm@10 4302 (declare process-annotation)
rlm@10 4303 (defn- add-annotation [^clojure.asm.AnnotationVisitor av name v]
rlm@10 4304 (cond
rlm@10 4305 (vector? v) (let [avec (.visitArray av name)]
rlm@10 4306 (doseq [vval v]
rlm@10 4307 (add-annotation avec "value" vval))
rlm@10 4308 (.visitEnd avec))
rlm@10 4309 (symbol? v) (let [ev (eval v)]
rlm@10 4310 (cond
rlm@10 4311 (instance? java.lang.Enum ev)
rlm@10 4312 (.visitEnum av name (descriptor (class ev)) (str ev))
rlm@10 4313 (class? ev) (.visit av name (clojure.asm.Type/getType ev))
rlm@10 4314 :else (throw (IllegalArgumentException.
rlm@10 4315 (str "Unsupported annotation value: " v " of class " (class ev))))))
rlm@10 4316 (seq? v) (let [[nested nv] v
rlm@10 4317 c (resolve nested)
rlm@10 4318 nav (.visitAnnotation av name (descriptor c))]
rlm@10 4319 (process-annotation nav nv)
rlm@10 4320 (.visitEnd nav))
rlm@10 4321 :else (.visit av name v)))
rlm@10 4322
rlm@10 4323 (defn- process-annotation [av v]
rlm@10 4324 (if (map? v)
rlm@10 4325 (doseq [[k v] v]
rlm@10 4326 (add-annotation av (name k) v))
rlm@10 4327 (add-annotation av "value" v)))
rlm@10 4328
rlm@10 4329 (defn- add-annotations
rlm@10 4330 ([visitor m] (add-annotations visitor m nil))
rlm@10 4331 ([visitor m i]
rlm@10 4332 (doseq [[k v] m]
rlm@10 4333 (when (symbol? k)
rlm@10 4334 (when-let [c (resolve k)]
rlm@10 4335 (when (is-annotation? c)
rlm@10 4336 ;this is known duck/reflective as no common base of ASM Visitors
rlm@10 4337 (let [av (if i
rlm@10 4338 (.visitParameterAnnotation visitor i (descriptor c)
rlm@10 4339 (is-runtime-annotation? c))
rlm@10 4340 (.visitAnnotation visitor (descriptor c)
rlm@10 4341 (is-runtime-annotation? c)))]
rlm@10 4342 (process-annotation av v)
rlm@10 4343 (.visitEnd av))))))))
rlm@10 4344
rlm@10 4345 (defn alter-var-root
rlm@10 4346 "Atomically alters the root binding of var v by applying f to its
rlm@10 4347 current value plus any args"
rlm@10 4348 {:added "1.0"}
rlm@10 4349 [^clojure.lang.Var v f & args] (.alterRoot v f args))
rlm@10 4350
rlm@10 4351 (defn bound?
rlm@10 4352 "Returns true if all of the vars provided as arguments have any bound value, root or thread-local.
rlm@10 4353 Implies that deref'ing the provided vars will succeed. Returns true if no vars are provided."
rlm@10 4354 {:added "1.2"}
rlm@10 4355 [& vars]
rlm@10 4356 (every? #(.isBound ^clojure.lang.Var %) vars))
rlm@10 4357
rlm@10 4358 (defn thread-bound?
rlm@10 4359 "Returns true if all of the vars provided as arguments have thread-local bindings.
rlm@10 4360 Implies that set!'ing the provided vars will succeed. Returns true if no vars are provided."
rlm@10 4361 {:added "1.2"}
rlm@10 4362 [& vars]
rlm@10 4363 (every? #(.getThreadBinding ^clojure.lang.Var %) vars))
rlm@10 4364
rlm@10 4365 (defn make-hierarchy
rlm@10 4366 "Creates a hierarchy object for use with derive, isa? etc."
rlm@10 4367 {:added "1.0"}
rlm@10 4368 [] {:parents {} :descendants {} :ancestors {}})
rlm@10 4369
rlm@10 4370 (def ^{:private true}
rlm@10 4371 global-hierarchy (make-hierarchy))
rlm@10 4372
rlm@10 4373 (defn not-empty
rlm@10 4374 "If coll is empty, returns nil, else coll"
rlm@10 4375 {:added "1.0"}
rlm@10 4376 [coll] (when (seq coll) coll))
rlm@10 4377
rlm@10 4378 (defn bases
rlm@10 4379 "Returns the immediate superclass and direct interfaces of c, if any"
rlm@10 4380 {:added "1.0"}
rlm@10 4381 [^Class c]
rlm@10 4382 (when c
rlm@10 4383 (let [i (.getInterfaces c)
rlm@10 4384 s (.getSuperclass c)]
rlm@10 4385 (not-empty
rlm@10 4386 (if s (cons s i) i)))))
rlm@10 4387
rlm@10 4388 (defn supers
rlm@10 4389 "Returns the immediate and indirect superclasses and interfaces of c, if any"
rlm@10 4390 {:added "1.0"}
rlm@10 4391 [^Class class]
rlm@10 4392 (loop [ret (set (bases class)) cs ret]
rlm@10 4393 (if (seq cs)
rlm@10 4394 (let [c (first cs) bs (bases c)]
rlm@10 4395 (recur (into ret bs) (into (disj cs c) bs)))
rlm@10 4396 (not-empty ret))))
rlm@10 4397
rlm@10 4398 (defn isa?
rlm@10 4399 "Returns true if (= child parent), or child is directly or indirectly derived from
rlm@10 4400 parent, either via a Java type inheritance relationship or a
rlm@10 4401 relationship established via derive. h must be a hierarchy obtained
rlm@10 4402 from make-hierarchy, if not supplied defaults to the global
rlm@10 4403 hierarchy"
rlm@10 4404 {:added "1.0"}
rlm@10 4405 ([child parent] (isa? global-hierarchy child parent))
rlm@10 4406 ([h child parent]
rlm@10 4407 (or (= child parent)
rlm@10 4408 (and (class? parent) (class? child)
rlm@10 4409 (. ^Class parent isAssignableFrom child))
rlm@10 4410 (contains? ((:ancestors h) child) parent)
rlm@10 4411 (and (class? child) (some #(contains? ((:ancestors h) %) parent) (supers child)))
rlm@10 4412 (and (vector? parent) (vector? child)
rlm@10 4413 (= (count parent) (count child))
rlm@10 4414 (loop [ret true i 0]
rlm@10 4415 (if (or (not ret) (= i (count parent)))
rlm@10 4416 ret
rlm@10 4417 (recur (isa? h (child i) (parent i)) (inc i))))))))
rlm@10 4418
rlm@10 4419 (defn parents
rlm@10 4420 "Returns the immediate parents of tag, either via a Java type
rlm@10 4421 inheritance relationship or a relationship established via derive. h
rlm@10 4422 must be a hierarchy obtained from make-hierarchy, if not supplied
rlm@10 4423 defaults to the global hierarchy"
rlm@10 4424 {:added "1.0"}
rlm@10 4425 ([tag] (parents global-hierarchy tag))
rlm@10 4426 ([h tag] (not-empty
rlm@10 4427 (let [tp (get (:parents h) tag)]
rlm@10 4428 (if (class? tag)
rlm@10 4429 (into (set (bases tag)) tp)
rlm@10 4430 tp)))))
rlm@10 4431
rlm@10 4432 (defn ancestors
rlm@10 4433 "Returns the immediate and indirect parents of tag, either via a Java type
rlm@10 4434 inheritance relationship or a relationship established via derive. h
rlm@10 4435 must be a hierarchy obtained from make-hierarchy, if not supplied
rlm@10 4436 defaults to the global hierarchy"
rlm@10 4437 {:added "1.0"}
rlm@10 4438 ([tag] (ancestors global-hierarchy tag))
rlm@10 4439 ([h tag] (not-empty
rlm@10 4440 (let [ta (get (:ancestors h) tag)]
rlm@10 4441 (if (class? tag)
rlm@10 4442 (let [superclasses (set (supers tag))]
rlm@10 4443 (reduce into superclasses
rlm@10 4444 (cons ta
rlm@10 4445 (map #(get (:ancestors h) %) superclasses))))
rlm@10 4446 ta)))))
rlm@10 4447
rlm@10 4448 (defn descendants
rlm@10 4449 "Returns the immediate and indirect children of tag, through a
rlm@10 4450 relationship established via derive. h must be a hierarchy obtained
rlm@10 4451 from make-hierarchy, if not supplied defaults to the global
rlm@10 4452 hierarchy. Note: does not work on Java type inheritance
rlm@10 4453 relationships."
rlm@10 4454 {:added "1.0"}
rlm@10 4455 ([tag] (descendants global-hierarchy tag))
rlm@10 4456 ([h tag] (if (class? tag)
rlm@10 4457 (throw (java.lang.UnsupportedOperationException. "Can't get descendants of classes"))
rlm@10 4458 (not-empty (get (:descendants h) tag)))))
rlm@10 4459
rlm@10 4460 (defn derive
rlm@10 4461 "Establishes a parent/child relationship between parent and
rlm@10 4462 tag. Parent must be a namespace-qualified symbol or keyword and
rlm@10 4463 child can be either a namespace-qualified symbol or keyword or a
rlm@10 4464 class. h must be a hierarchy obtained from make-hierarchy, if not
rlm@10 4465 supplied defaults to, and modifies, the global hierarchy."
rlm@10 4466 {:added "1.0"}
rlm@10 4467 ([tag parent]
rlm@10 4468 (assert (namespace parent))
rlm@10 4469 (assert (or (class? tag) (and (instance? clojure.lang.Named tag) (namespace tag))))
rlm@10 4470
rlm@10 4471 (alter-var-root #'global-hierarchy derive tag parent) nil)
rlm@10 4472 ([h tag parent]
rlm@10 4473 (assert (not= tag parent))
rlm@10 4474 (assert (or (class? tag) (instance? clojure.lang.Named tag)))
rlm@10 4475 (assert (instance? clojure.lang.Named parent))
rlm@10 4476
rlm@10 4477 (let [tp (:parents h)
rlm@10 4478 td (:descendants h)
rlm@10 4479 ta (:ancestors h)
rlm@10 4480 tf (fn [m source sources target targets]
rlm@10 4481 (reduce (fn [ret k]
rlm@10 4482 (assoc ret k
rlm@10 4483 (reduce conj (get targets k #{}) (cons target (targets target)))))
rlm@10 4484 m (cons source (sources source))))]
rlm@10 4485 (or
rlm@10 4486 (when-not (contains? (tp tag) parent)
rlm@10 4487 (when (contains? (ta tag) parent)
rlm@10 4488 (throw (Exception. (print-str tag "already has" parent "as ancestor"))))
rlm@10 4489 (when (contains? (ta parent) tag)
rlm@10 4490 (throw (Exception. (print-str "Cyclic derivation:" parent "has" tag "as ancestor"))))
rlm@10 4491 {:parents (assoc (:parents h) tag (conj (get tp tag #{}) parent))
rlm@10 4492 :ancestors (tf (:ancestors h) tag td parent ta)
rlm@10 4493 :descendants (tf (:descendants h) parent ta tag td)})
rlm@10 4494 h))))
rlm@10 4495
rlm@10 4496 (declare flatten)
rlm@10 4497
rlm@10 4498 (defn underive
rlm@10 4499 "Removes a parent/child relationship between parent and
rlm@10 4500 tag. h must be a hierarchy obtained from make-hierarchy, if not
rlm@10 4501 supplied defaults to, and modifies, the global hierarchy."
rlm@10 4502 {:added "1.0"}
rlm@10 4503 ([tag parent] (alter-var-root #'global-hierarchy underive tag parent) nil)
rlm@10 4504 ([h tag parent]
rlm@10 4505 (let [parentMap (:parents h)
rlm@10 4506 childsParents (if (parentMap tag)
rlm@10 4507 (disj (parentMap tag) parent) #{})
rlm@10 4508 newParents (if (not-empty childsParents)
rlm@10 4509 (assoc parentMap tag childsParents)
rlm@10 4510 (dissoc parentMap tag))
rlm@10 4511 deriv-seq (flatten (map #(cons (key %) (interpose (key %) (val %)))
rlm@10 4512 (seq newParents)))]
rlm@10 4513 (if (contains? (parentMap tag) parent)
rlm@10 4514 (reduce #(apply derive %1 %2) (make-hierarchy)
rlm@10 4515 (partition 2 deriv-seq))
rlm@10 4516 h))))
rlm@10 4517
rlm@10 4518
rlm@10 4519 (defn distinct?
rlm@10 4520 "Returns true if no two of the arguments are ="
rlm@10 4521 {:tag Boolean
rlm@10 4522 :added "1.0"}
rlm@10 4523 ([x] true)
rlm@10 4524 ([x y] (not (= x y)))
rlm@10 4525 ([x y & more]
rlm@10 4526 (if (not= x y)
rlm@10 4527 (loop [s #{x y} [x & etc :as xs] more]
rlm@10 4528 (if xs
rlm@10 4529 (if (contains? s x)
rlm@10 4530 false
rlm@10 4531 (recur (conj s x) etc))
rlm@10 4532 true))
rlm@10 4533 false)))
rlm@10 4534
rlm@10 4535 (defn resultset-seq
rlm@10 4536 "Creates and returns a lazy sequence of structmaps corresponding to
rlm@10 4537 the rows in the java.sql.ResultSet rs"
rlm@10 4538 {:added "1.0"}
rlm@10 4539 [^java.sql.ResultSet rs]
rlm@10 4540 (let [rsmeta (. rs (getMetaData))
rlm@10 4541 idxs (range 1 (inc (. rsmeta (getColumnCount))))
rlm@10 4542 keys (map (comp keyword #(.toLowerCase ^String %))
rlm@10 4543 (map (fn [i] (. rsmeta (getColumnLabel i))) idxs))
rlm@10 4544 check-keys
rlm@10 4545 (or (apply distinct? keys)
rlm@10 4546 (throw (Exception. "ResultSet must have unique column labels")))
rlm@10 4547 row-struct (apply create-struct keys)
rlm@10 4548 row-values (fn [] (map (fn [^Integer i] (. rs (getObject i))) idxs))
rlm@10 4549 rows (fn thisfn []
rlm@10 4550 (when (. rs (next))
rlm@10 4551 (cons (apply struct row-struct (row-values)) (lazy-seq (thisfn)))))]
rlm@10 4552 (rows)))
rlm@10 4553
rlm@10 4554 (defn iterator-seq
rlm@10 4555 "Returns a seq on a java.util.Iterator. Note that most collections
rlm@10 4556 providing iterators implement Iterable and thus support seq directly."
rlm@10 4557 {:added "1.0"}
rlm@10 4558 [iter]
rlm@10 4559 (clojure.lang.IteratorSeq/create iter))
rlm@10 4560
rlm@10 4561 (defn enumeration-seq
rlm@10 4562 "Returns a seq on a java.util.Enumeration"
rlm@10 4563 {:added "1.0"}
rlm@10 4564 [e]
rlm@10 4565 (clojure.lang.EnumerationSeq/create e))
rlm@10 4566
rlm@10 4567 (defn format
rlm@10 4568 "Formats a string using java.lang.String.format, see java.util.Formatter for format
rlm@10 4569 string syntax"
rlm@10 4570 {:tag String
rlm@10 4571 :added "1.0"}
rlm@10 4572 [fmt & args]
rlm@10 4573 (String/format fmt (to-array args)))
rlm@10 4574
rlm@10 4575 (defn printf
rlm@10 4576 "Prints formatted output, as per format"
rlm@10 4577 {:added "1.0"}
rlm@10 4578 [fmt & args]
rlm@10 4579 (print (apply format fmt args)))
rlm@10 4580
rlm@10 4581 (declare gen-class)
rlm@10 4582
rlm@10 4583 (defmacro with-loading-context [& body]
rlm@10 4584 `((fn loading# []
rlm@10 4585 (. clojure.lang.Var (pushThreadBindings {clojure.lang.Compiler/LOADER
rlm@10 4586 (.getClassLoader (.getClass ^Object loading#))}))
rlm@10 4587 (try
rlm@10 4588 ~@body
rlm@10 4589 (finally
rlm@10 4590 (. clojure.lang.Var (popThreadBindings)))))))
rlm@10 4591
rlm@10 4592 (defmacro ns
rlm@10 4593 "Sets *ns* to the namespace named by name (unevaluated), creating it
rlm@10 4594 if needed. references can be zero or more of: (:refer-clojure ...)
rlm@10 4595 (:require ...) (:use ...) (:import ...) (:load ...) (:gen-class)
rlm@10 4596 with the syntax of refer-clojure/require/use/import/load/gen-class
rlm@10 4597 respectively, except the arguments are unevaluated and need not be
rlm@10 4598 quoted. (:gen-class ...), when supplied, defaults to :name
rlm@10 4599 corresponding to the ns name, :main true, :impl-ns same as ns, and
rlm@10 4600 :init-impl-ns true. All options of gen-class are
rlm@10 4601 supported. The :gen-class directive is ignored when not
rlm@10 4602 compiling. If :gen-class is not supplied, when compiled only an
rlm@10 4603 nsname__init.class will be generated. If :refer-clojure is not used, a
rlm@10 4604 default (refer 'clojure) is used. Use of ns is preferred to
rlm@10 4605 individual calls to in-ns/require/use/import:
rlm@10 4606
rlm@10 4607 (ns foo.bar
rlm@10 4608 (:refer-clojure :exclude [ancestors printf])
rlm@10 4609 (:require (clojure.contrib sql sql.tests))
rlm@10 4610 (:use (my.lib this that))
rlm@10 4611 (:import (java.util Date Timer Random)
rlm@10 4612 (java.sql Connection Statement)))"
rlm@10 4613 {:arglists '([name docstring? attr-map? references*])
rlm@10 4614 :added "1.0"}
rlm@10 4615 [name & references]
rlm@10 4616 (let [process-reference
rlm@10 4617 (fn [[kname & args]]
rlm@10 4618 `(~(symbol "clojure.core" (clojure.core/name kname))
rlm@10 4619 ~@(map #(list 'quote %) args)))
rlm@10 4620 docstring (when (string? (first references)) (first references))
rlm@10 4621 references (if docstring (next references) references)
rlm@10 4622 name (if docstring
rlm@10 4623 (vary-meta name assoc :doc docstring)
rlm@10 4624 name)
rlm@10 4625 metadata (when (map? (first references)) (first references))
rlm@10 4626 references (if metadata (next references) references)
rlm@10 4627 name (if metadata
rlm@10 4628 (vary-meta name merge metadata)
rlm@10 4629 name)
rlm@10 4630 gen-class-clause (first (filter #(= :gen-class (first %)) references))
rlm@10 4631 gen-class-call
rlm@10 4632 (when gen-class-clause
rlm@10 4633 (list* `gen-class :name (.replace (str name) \- \_) :impl-ns name :main true (next gen-class-clause)))
rlm@10 4634 references (remove #(= :gen-class (first %)) references)
rlm@10 4635 ;ns-effect (clojure.core/in-ns name)
rlm@10 4636 ]
rlm@10 4637 `(do
rlm@10 4638 (clojure.core/in-ns '~name)
rlm@10 4639 (with-loading-context
rlm@10 4640 ~@(when gen-class-call (list gen-class-call))
rlm@10 4641 ~@(when (and (not= name 'clojure.core) (not-any? #(= :refer-clojure (first %)) references))
rlm@10 4642 `((clojure.core/refer '~'clojure.core)))
rlm@10 4643 ~@(map process-reference references)))))
rlm@10 4644
rlm@10 4645 (defmacro refer-clojure
rlm@10 4646 "Same as (refer 'clojure.core <filters>)"
rlm@10 4647 {:added "1.0"}
rlm@10 4648 [& filters]
rlm@10 4649 `(clojure.core/refer '~'clojure.core ~@filters))
rlm@10 4650
rlm@10 4651 (defmacro defonce
rlm@10 4652 "defs name to have the root value of the expr iff the named var has no root value,
rlm@10 4653 else expr is unevaluated"
rlm@10 4654 {:added "1.0"}
rlm@10 4655 [name expr]
rlm@10 4656 `(let [v# (def ~name)]
rlm@10 4657 (when-not (.hasRoot v#)
rlm@10 4658 (def ~name ~expr))))
rlm@10 4659
rlm@10 4660 ;;;;;;;;;;; require/use/load, contributed by Stephen C. Gilardi ;;;;;;;;;;;;;;;;;;
rlm@10 4661
rlm@10 4662 (defonce
rlm@10 4663 ^{:private true
rlm@10 4664 :doc "A ref to a sorted set of symbols representing loaded libs"}
rlm@10 4665 *loaded-libs* (ref (sorted-set)))
rlm@10 4666
rlm@10 4667 (defonce
rlm@10 4668 ^{:private true
rlm@10 4669 :doc "the set of paths currently being loaded by this thread"}
rlm@10 4670 *pending-paths* #{})
rlm@10 4671
rlm@10 4672 (defonce
rlm@10 4673 ^{:private true :doc
rlm@10 4674 "True while a verbose load is pending"}
rlm@10 4675 *loading-verbosely* false)
rlm@10 4676
rlm@10 4677 (defn- throw-if
rlm@10 4678 "Throws an exception with a message if pred is true"
rlm@10 4679 [pred fmt & args]
rlm@10 4680 (when pred
rlm@10 4681 (let [^String message (apply format fmt args)
rlm@10 4682 exception (Exception. message)
rlm@10 4683 raw-trace (.getStackTrace exception)
rlm@10 4684 boring? #(not= (.getMethodName ^StackTraceElement %) "doInvoke")
rlm@10 4685 trace (into-array (drop 2 (drop-while boring? raw-trace)))]
rlm@10 4686 (.setStackTrace exception trace)
rlm@10 4687 (throw exception))))
rlm@10 4688
rlm@10 4689 (defn- libspec?
rlm@10 4690 "Returns true if x is a libspec"
rlm@10 4691 [x]
rlm@10 4692 (or (symbol? x)
rlm@10 4693 (and (vector? x)
rlm@10 4694 (or
rlm@10 4695 (nil? (second x))
rlm@10 4696 (keyword? (second x))))))
rlm@10 4697
rlm@10 4698 (defn- prependss
rlm@10 4699 "Prepends a symbol or a seq to coll"
rlm@10 4700 [x coll]
rlm@10 4701 (if (symbol? x)
rlm@10 4702 (cons x coll)
rlm@10 4703 (concat x coll)))
rlm@10 4704
rlm@10 4705 (defn- root-resource
rlm@10 4706 "Returns the root directory path for a lib"
rlm@10 4707 {:tag String}
rlm@10 4708 [lib]
rlm@10 4709 (str \/
rlm@10 4710 (.. (name lib)
rlm@10 4711 (replace \- \_)
rlm@10 4712 (replace \. \/))))
rlm@10 4713
rlm@10 4714 (defn- root-directory
rlm@10 4715 "Returns the root resource path for a lib"
rlm@10 4716 [lib]
rlm@10 4717 (let [d (root-resource lib)]
rlm@10 4718 (subs d 0 (.lastIndexOf d "/"))))
rlm@10 4719
rlm@10 4720 (declare load)
rlm@10 4721
rlm@10 4722 (defn- load-one
rlm@10 4723 "Loads a lib given its name. If need-ns, ensures that the associated
rlm@10 4724 namespace exists after loading. If require, records the load so any
rlm@10 4725 duplicate loads can be skipped."
rlm@10 4726 [lib need-ns require]
rlm@10 4727 (load (root-resource lib))
rlm@10 4728 (throw-if (and need-ns (not (find-ns lib)))
rlm@10 4729 "namespace '%s' not found after loading '%s'"
rlm@10 4730 lib (root-resource lib))
rlm@10 4731 (when require
rlm@10 4732 (dosync
rlm@10 4733 (commute *loaded-libs* conj lib))))
rlm@10 4734
rlm@10 4735 (defn- load-all
rlm@10 4736 "Loads a lib given its name and forces a load of any libs it directly or
rlm@10 4737 indirectly loads. If need-ns, ensures that the associated namespace
rlm@10 4738 exists after loading. If require, records the load so any duplicate loads
rlm@10 4739 can be skipped."
rlm@10 4740 [lib need-ns require]
rlm@10 4741 (dosync
rlm@10 4742 (commute *loaded-libs* #(reduce conj %1 %2)
rlm@10 4743 (binding [*loaded-libs* (ref (sorted-set))]
rlm@10 4744 (load-one lib need-ns require)
rlm@10 4745 @*loaded-libs*))))
rlm@10 4746
rlm@10 4747 (defn- load-lib
rlm@10 4748 "Loads a lib with options"
rlm@10 4749 [prefix lib & options]
rlm@10 4750 (throw-if (and prefix (pos? (.indexOf (name lib) (int \.))))
rlm@10 4751 "lib names inside prefix lists must not contain periods")
rlm@10 4752 (let [lib (if prefix (symbol (str prefix \. lib)) lib)
rlm@10 4753 opts (apply hash-map options)
rlm@10 4754 {:keys [as reload reload-all require use verbose]} opts
rlm@10 4755 loaded (contains? @*loaded-libs* lib)
rlm@10 4756 load (cond reload-all
rlm@10 4757 load-all
rlm@10 4758 (or reload (not require) (not loaded))
rlm@10 4759 load-one)
rlm@10 4760 need-ns (or as use)
rlm@10 4761 filter-opts (select-keys opts '(:exclude :only :rename))]
rlm@10 4762 (binding [*loading-verbosely* (or *loading-verbosely* verbose)]
rlm@10 4763 (if load
rlm@10 4764 (load lib need-ns require)
rlm@10 4765 (throw-if (and need-ns (not (find-ns lib)))
rlm@10 4766 "namespace '%s' not found" lib))
rlm@10 4767 (when (and need-ns *loading-verbosely*)
rlm@10 4768 (printf "(clojure.core/in-ns '%s)\n" (ns-name *ns*)))
rlm@10 4769 (when as
rlm@10 4770 (when *loading-verbosely*
rlm@10 4771 (printf "(clojure.core/alias '%s '%s)\n" as lib))
rlm@10 4772 (alias as lib))
rlm@10 4773 (when use
rlm@10 4774 (when *loading-verbosely*
rlm@10 4775 (printf "(clojure.core/refer '%s" lib)
rlm@10 4776 (doseq [opt filter-opts]
rlm@10 4777 (printf " %s '%s" (key opt) (print-str (val opt))))
rlm@10 4778 (printf ")\n"))
rlm@10 4779 (apply refer lib (mapcat seq filter-opts))))))
rlm@10 4780
rlm@10 4781 (defn- load-libs
rlm@10 4782 "Loads libs, interpreting libspecs, prefix lists, and flags for
rlm@10 4783 forwarding to load-lib"
rlm@10 4784 [& args]
rlm@10 4785 (let [flags (filter keyword? args)
rlm@10 4786 opts (interleave flags (repeat true))
rlm@10 4787 args (filter (complement keyword?) args)]
rlm@10 4788 ; check for unsupported options
rlm@10 4789 (let [supported #{:as :reload :reload-all :require :use :verbose}
rlm@10 4790 unsupported (seq (remove supported flags))]
rlm@10 4791 (throw-if unsupported
rlm@10 4792 (apply str "Unsupported option(s) supplied: "
rlm@10 4793 (interpose \, unsupported))))
rlm@10 4794 ; check a load target was specified
rlm@10 4795 (throw-if (not (seq args)) "Nothing specified to load")
rlm@10 4796 (doseq [arg args]
rlm@10 4797 (if (libspec? arg)
rlm@10 4798 (apply load-lib nil (prependss arg opts))
rlm@10 4799 (let [[prefix & args] arg]
rlm@10 4800 (throw-if (nil? prefix) "prefix cannot be nil")
rlm@10 4801 (doseq [arg args]
rlm@10 4802 (apply load-lib prefix (prependss arg opts))))))))
rlm@10 4803
rlm@10 4804 ;; Public
rlm@10 4805
rlm@10 4806
rlm@10 4807 (defn require
rlm@10 4808 "Loads libs, skipping any that are already loaded. Each argument is
rlm@10 4809 either a libspec that identifies a lib, a prefix list that identifies
rlm@10 4810 multiple libs whose names share a common prefix, or a flag that modifies
rlm@10 4811 how all the identified libs are loaded. Use :require in the ns macro
rlm@10 4812 in preference to calling this directly.
rlm@10 4813
rlm@10 4814 Libs
rlm@10 4815
rlm@10 4816 A 'lib' is a named set of resources in classpath whose contents define a
rlm@10 4817 library of Clojure code. Lib names are symbols and each lib is associated
rlm@10 4818 with a Clojure namespace and a Java package that share its name. A lib's
rlm@10 4819 name also locates its root directory within classpath using Java's
rlm@10 4820 package name to classpath-relative path mapping. All resources in a lib
rlm@10 4821 should be contained in the directory structure under its root directory.
rlm@10 4822 All definitions a lib makes should be in its associated namespace.
rlm@10 4823
rlm@10 4824 'require loads a lib by loading its root resource. The root resource path
rlm@10 4825 is derived from the lib name in the following manner:
rlm@10 4826 Consider a lib named by the symbol 'x.y.z; it has the root directory
rlm@10 4827 <classpath>/x/y/, and its root resource is <classpath>/x/y/z.clj. The root
rlm@10 4828 resource should contain code to create the lib's namespace (usually by using
rlm@10 4829 the ns macro) and load any additional lib resources.
rlm@10 4830
rlm@10 4831 Libspecs
rlm@10 4832
rlm@10 4833 A libspec is a lib name or a vector containing a lib name followed by
rlm@10 4834 options expressed as sequential keywords and arguments.
rlm@10 4835
rlm@10 4836 Recognized options: :as
rlm@10 4837 :as takes a symbol as its argument and makes that symbol an alias to the
rlm@10 4838 lib's namespace in the current namespace.
rlm@10 4839
rlm@10 4840 Prefix Lists
rlm@10 4841
rlm@10 4842 It's common for Clojure code to depend on several libs whose names have
rlm@10 4843 the same prefix. When specifying libs, prefix lists can be used to reduce
rlm@10 4844 repetition. A prefix list contains the shared prefix followed by libspecs
rlm@10 4845 with the shared prefix removed from the lib names. After removing the
rlm@10 4846 prefix, the names that remain must not contain any periods.
rlm@10 4847
rlm@10 4848 Flags
rlm@10 4849
rlm@10 4850 A flag is a keyword.
rlm@10 4851 Recognized flags: :reload, :reload-all, :verbose
rlm@10 4852 :reload forces loading of all the identified libs even if they are
rlm@10 4853 already loaded
rlm@10 4854 :reload-all implies :reload and also forces loading of all libs that the
rlm@10 4855 identified libs directly or indirectly load via require or use
rlm@10 4856 :verbose triggers printing information about each load, alias, and refer
rlm@10 4857
rlm@10 4858 Example:
rlm@10 4859
rlm@10 4860 The following would load the libraries clojure.zip and clojure.set
rlm@10 4861 abbreviated as 's'.
rlm@10 4862
rlm@10 4863 (require '(clojure zip [set :as s]))"
rlm@10 4864 {:added "1.0"}
rlm@10 4865
rlm@10 4866 [& args]
rlm@10 4867 (apply load-libs :require args))
rlm@10 4868
rlm@10 4869 (defn use
rlm@10 4870 "Like 'require, but also refers to each lib's namespace using
rlm@10 4871 clojure.core/refer. Use :use in the ns macro in preference to calling
rlm@10 4872 this directly.
rlm@10 4873
rlm@10 4874 'use accepts additional options in libspecs: :exclude, :only, :rename.
rlm@10 4875 The arguments and semantics for :exclude, :only, and :rename are the same
rlm@10 4876 as those documented for clojure.core/refer."
rlm@10 4877 {:added "1.0"}
rlm@10 4878 [& args] (apply load-libs :require :use args))
rlm@10 4879
rlm@10 4880 (defn loaded-libs
rlm@10 4881 "Returns a sorted set of symbols naming the currently loaded libs"
rlm@10 4882 {:added "1.0"}
rlm@10 4883 [] @*loaded-libs*)
rlm@10 4884
rlm@10 4885 (defn load
rlm@10 4886 "Loads Clojure code from resources in classpath. A path is interpreted as
rlm@10 4887 classpath-relative if it begins with a slash or relative to the root
rlm@10 4888 directory for the current namespace otherwise."
rlm@10 4889 {:added "1.0"}
rlm@10 4890 [& paths]
rlm@10 4891 (doseq [^String path paths]
rlm@10 4892 (let [^String path (if (.startsWith path "/")
rlm@10 4893 path
rlm@10 4894 (str (root-directory (ns-name *ns*)) \/ path))]
rlm@10 4895 (when *loading-verbosely*
rlm@10 4896 (printf "(clojure.core/load \"%s\")\n" path)
rlm@10 4897 (flush))
rlm@10 4898 ; (throw-if (*pending-paths* path)
rlm@10 4899 ; "cannot load '%s' again while it is loading"
rlm@10 4900 ; path)
rlm@10 4901 (when-not (*pending-paths* path)
rlm@10 4902 (binding [*pending-paths* (conj *pending-paths* path)]
rlm@10 4903 (clojure.lang.RT/load (.substring path 1)))))))
rlm@10 4904
rlm@10 4905 (defn compile
rlm@10 4906 "Compiles the namespace named by the symbol lib into a set of
rlm@10 4907 classfiles. The source for the lib must be in a proper
rlm@10 4908 classpath-relative directory. The output files will go into the
rlm@10 4909 directory specified by *compile-path*, and that directory too must
rlm@10 4910 be in the classpath."
rlm@10 4911 {:added "1.0"}
rlm@10 4912 [lib]
rlm@10 4913 (binding [*compile-files* true]
rlm@10 4914 (load-one lib true true))
rlm@10 4915 lib)
rlm@10 4916
rlm@10 4917 ;;;;;;;;;;;;; nested associative ops ;;;;;;;;;;;
rlm@10 4918
rlm@10 4919 (defn get-in
rlm@10 4920 "Returns the value in a nested associative structure,
rlm@10 4921 where ks is a sequence of ke(ys. Returns nil if the key is not present,
rlm@10 4922 or the not-found value if supplied."
rlm@10 4923 {:added "1.2"}
rlm@10 4924 ([m ks]
rlm@10 4925 (reduce get m ks))
rlm@10 4926 ([m ks not-found]
rlm@10 4927 (loop [sentinel (Object.)
rlm@10 4928 m m
rlm@10 4929 ks (seq ks)]
rlm@10 4930 (if ks
rlm@10 4931 (let [m (get m (first ks) sentinel)]
rlm@10 4932 (if (identical? sentinel m)
rlm@10 4933 not-found
rlm@10 4934 (recur sentinel m (next ks))))
rlm@10 4935 m))))
rlm@10 4936
rlm@10 4937 (defn assoc-in
rlm@10 4938 "Associates a value in a nested associative structure, where ks is a
rlm@10 4939 sequence of keys and v is the new value and returns a new nested structure.
rlm@10 4940 If any levels do not exist, hash-maps will be created."
rlm@10 4941 {:added "1.0"}
rlm@10 4942 [m [k & ks] v]
rlm@10 4943 (if ks
rlm@10 4944 (assoc m k (assoc-in (get m k) ks v))
rlm@10 4945 (assoc m k v)))
rlm@10 4946
rlm@10 4947 (defn update-in
rlm@10 4948 "'Updates' a value in a nested associative structure, where ks is a
rlm@10 4949 sequence of keys and f is a function that will take the old value
rlm@10 4950 and any supplied args and return the new value, and returns a new
rlm@10 4951 nested structure. If any levels do not exist, hash-maps will be
rlm@10 4952 created."
rlm@10 4953 {:added "1.0"}
rlm@10 4954 ([m [k & ks] f & args]
rlm@10 4955 (if ks
rlm@10 4956 (assoc m k (apply update-in (get m k) ks f args))
rlm@10 4957 (assoc m k (apply f (get m k) args)))))
rlm@10 4958
rlm@10 4959
rlm@10 4960 (defn empty?
rlm@10 4961 "Returns true if coll has no items - same as (not (seq coll)).
rlm@10 4962 Please use the idiom (seq x) rather than (not (empty? x))"
rlm@10 4963 {:added "1.0"}
rlm@10 4964 [coll] (not (seq coll)))
rlm@10 4965
rlm@10 4966 (defn coll?
rlm@10 4967 "Returns true if x implements IPersistentCollection"
rlm@10 4968 {:added "1.0"}
rlm@10 4969 [x] (instance? clojure.lang.IPersistentCollection x))
rlm@10 4970
rlm@10 4971 (defn list?
rlm@10 4972 "Returns true if x implements IPersistentList"
rlm@10 4973 {:added "1.0"}
rlm@10 4974 [x] (instance? clojure.lang.IPersistentList x))
rlm@10 4975
rlm@10 4976 (defn set?
rlm@10 4977 "Returns true if x implements IPersistentSet"
rlm@10 4978 {:added "1.0"}
rlm@10 4979 [x] (instance? clojure.lang.IPersistentSet x))
rlm@10 4980
rlm@10 4981 (defn ifn?
rlm@10 4982 "Returns true if x implements IFn. Note that many data structures
rlm@10 4983 (e.g. sets and maps) implement IFn"
rlm@10 4984 {:added "1.0"}
rlm@10 4985 [x] (instance? clojure.lang.IFn x))
rlm@10 4986
rlm@10 4987 (defn fn?
rlm@10 4988 "Returns true if x implements Fn, i.e. is an object created via fn."
rlm@10 4989 {:added "1.0"}
rlm@10 4990 [x] (instance? clojure.lang.Fn x))
rlm@10 4991
rlm@10 4992
rlm@10 4993 (defn associative?
rlm@10 4994 "Returns true if coll implements Associative"
rlm@10 4995 {:added "1.0"}
rlm@10 4996 [coll] (instance? clojure.lang.Associative coll))
rlm@10 4997
rlm@10 4998 (defn sequential?
rlm@10 4999 "Returns true if coll implements Sequential"
rlm@10 5000 {:added "1.0"}
rlm@10 5001 [coll] (instance? clojure.lang.Sequential coll))
rlm@10 5002
rlm@10 5003 (defn sorted?
rlm@10 5004 "Returns true if coll implements Sorted"
rlm@10 5005 {:added "1.0"}
rlm@10 5006 [coll] (instance? clojure.lang.Sorted coll))
rlm@10 5007
rlm@10 5008 (defn counted?
rlm@10 5009 "Returns true if coll implements count in constant time"
rlm@10 5010 {:added "1.0"}
rlm@10 5011 [coll] (instance? clojure.lang.Counted coll))
rlm@10 5012
rlm@10 5013 (defn reversible?
rlm@10 5014 "Returns true if coll implements Reversible"
rlm@10 5015 {:added "1.0"}
rlm@10 5016 [coll] (instance? clojure.lang.Reversible coll))
rlm@10 5017
rlm@10 5018 (def
rlm@10 5019 ^{:doc "bound in a repl thread to the most recent value printed"
rlm@10 5020 :added "1.0"}
rlm@10 5021 *1)
rlm@10 5022
rlm@10 5023 (def
rlm@10 5024 ^{:doc "bound in a repl thread to the second most recent value printed"
rlm@10 5025 :added "1.0"}
rlm@10 5026 *2)
rlm@10 5027
rlm@10 5028 (def
rlm@10 5029 ^{:doc "bound in a repl thread to the third most recent value printed"
rlm@10 5030 :added "1.0"}
rlm@10 5031 *3)
rlm@10 5032
rlm@10 5033 (def
rlm@10 5034 ^{:doc "bound in a repl thread to the most recent exception caught by the repl"
rlm@10 5035 :added "1.0"}
rlm@10 5036 *e)
rlm@10 5037
rlm@10 5038 (defn trampoline
rlm@10 5039 "trampoline can be used to convert algorithms requiring mutual
rlm@10 5040 recursion without stack consumption. Calls f with supplied args, if
rlm@10 5041 any. If f returns a fn, calls that fn with no arguments, and
rlm@10 5042 continues to repeat, until the return value is not a fn, then
rlm@10 5043 returns that non-fn value. Note that if you want to return a fn as a
rlm@10 5044 final value, you must wrap it in some data structure and unpack it
rlm@10 5045 after trampoline returns."
rlm@10 5046 {:added "1.0"}
rlm@10 5047 ([f]
rlm@10 5048 (let [ret (f)]
rlm@10 5049 (if (fn? ret)
rlm@10 5050 (recur ret)
rlm@10 5051 ret)))
rlm@10 5052 ([f & args]
rlm@10 5053 (trampoline #(apply f args))))
rlm@10 5054
rlm@10 5055 (defn intern
rlm@10 5056 "Finds or creates a var named by the symbol name in the namespace
rlm@10 5057 ns (which can be a symbol or a namespace), setting its root binding
rlm@10 5058 to val if supplied. The namespace must exist. The var will adopt any
rlm@10 5059 metadata from the name symbol. Returns the var."
rlm@10 5060 {:added "1.0"}
rlm@10 5061 ([ns ^clojure.lang.Symbol name]
rlm@10 5062 (let [v (clojure.lang.Var/intern (the-ns ns) name)]
rlm@10 5063 (when (meta name) (.setMeta v (meta name)))
rlm@10 5064 v))
rlm@10 5065 ([ns name val]
rlm@10 5066 (let [v (clojure.lang.Var/intern (the-ns ns) name val)]
rlm@10 5067 (when (meta name) (.setMeta v (meta name)))
rlm@10 5068 v)))
rlm@10 5069
rlm@10 5070 (defmacro while
rlm@10 5071 "Repeatedly executes body while test expression is true. Presumes
rlm@10 5072 some side-effect will cause test to become false/nil. Returns nil"
rlm@10 5073 {:added "1.0"}
rlm@10 5074 [test & body]
rlm@10 5075 `(loop []
rlm@10 5076 (when ~test
rlm@10 5077 ~@body
rlm@10 5078 (recur))))
rlm@10 5079
rlm@10 5080 (defn memoize
rlm@10 5081 "Returns a memoized version of a referentially transparent function. The
rlm@10 5082 memoized version of the function keeps a cache of the mapping from arguments
rlm@10 5083 to results and, when calls with the same arguments are repeated often, has
rlm@10 5084 higher performance at the expense of higher memory use."
rlm@10 5085 {:added "1.0"}
rlm@10 5086 [f]
rlm@10 5087 (let [mem (atom {})]
rlm@10 5088 (fn [& args]
rlm@10 5089 (if-let [e (find @mem args)]
rlm@10 5090 (val e)
rlm@10 5091 (let [ret (apply f args)]
rlm@10 5092 (swap! mem assoc args ret)
rlm@10 5093 ret)))))
rlm@10 5094
rlm@10 5095 (defmacro condp
rlm@10 5096 "Takes a binary predicate, an expression, and a set of clauses.
rlm@10 5097 Each clause can take the form of either:
rlm@10 5098
rlm@10 5099 test-expr result-expr
rlm@10 5100
rlm@10 5101 test-expr :>> result-fn
rlm@10 5102
rlm@10 5103 Note :>> is an ordinary keyword.
rlm@10 5104
rlm@10 5105 For each clause, (pred test-expr expr) is evaluated. If it returns
rlm@10 5106 logical true, the clause is a match. If a binary clause matches, the
rlm@10 5107 result-expr is returned, if a ternary clause matches, its result-fn,
rlm@10 5108 which must be a unary function, is called with the result of the
rlm@10 5109 predicate as its argument, the result of that call being the return
rlm@10 5110 value of condp. A single default expression can follow the clauses,
rlm@10 5111 and its value will be returned if no clause matches. If no default
rlm@10 5112 expression is provided and no clause matches, an
rlm@10 5113 IllegalArgumentException is thrown."
rlm@10 5114 {:added "1.0"}
rlm@10 5115
rlm@10 5116 [pred expr & clauses]
rlm@10 5117 (let [gpred (gensym "pred__")
rlm@10 5118 gexpr (gensym "expr__")
rlm@10 5119 emit (fn emit [pred expr args]
rlm@10 5120 (let [[[a b c :as clause] more]
rlm@10 5121 (split-at (if (= :>> (second args)) 3 2) args)
rlm@10 5122 n (count clause)]
rlm@10 5123 (cond
rlm@10 5124 (= 0 n) `(throw (IllegalArgumentException. (str "No matching clause: " ~expr)))
rlm@10 5125 (= 1 n) a
rlm@10 5126 (= 2 n) `(if (~pred ~a ~expr)
rlm@10 5127 ~b
rlm@10 5128 ~(emit pred expr more))
rlm@10 5129 :else `(if-let [p# (~pred ~a ~expr)]
rlm@10 5130 (~c p#)
rlm@10 5131 ~(emit pred expr more)))))
rlm@10 5132 gres (gensym "res__")]
rlm@10 5133 `(let [~gpred ~pred
rlm@10 5134 ~gexpr ~expr]
rlm@10 5135 ~(emit gpred gexpr clauses))))
rlm@10 5136
rlm@10 5137 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; var documentation ;;;;;;;;;;;;;;;;;;;;;;;;;;
rlm@10 5138
rlm@10 5139 (alter-meta! #'*agent* assoc :added "1.0")
rlm@10 5140 (alter-meta! #'in-ns assoc :added "1.0")
rlm@10 5141 (alter-meta! #'load-file assoc :added "1.0")
rlm@10 5142
rlm@10 5143 (defmacro add-doc-and-meta {:private true} [name docstring meta]
rlm@10 5144 `(alter-meta! (var ~name) merge (assoc ~meta :doc ~docstring)))
rlm@10 5145
rlm@10 5146 (add-doc-and-meta *file*
rlm@10 5147 "The path of the file being evaluated, as a String.
rlm@10 5148
rlm@10 5149 Evaluates to nil when there is no file, eg. in the REPL."
rlm@10 5150 {:added "1.0"})
rlm@10 5151
rlm@10 5152 (add-doc-and-meta *command-line-args*
rlm@10 5153 "A sequence of the supplied command line arguments, or nil if
rlm@10 5154 none were supplied"
rlm@10 5155 {:added "1.0"})
rlm@10 5156
rlm@10 5157 (add-doc-and-meta *warn-on-reflection*
rlm@10 5158 "When set to true, the compiler will emit warnings when reflection is
rlm@10 5159 needed to resolve Java method calls or field accesses.
rlm@10 5160
rlm@10 5161 Defaults to false."
rlm@10 5162 {:added "1.0"})
rlm@10 5163
rlm@10 5164 (add-doc-and-meta *compile-path*
rlm@10 5165 "Specifies the directory where 'compile' will write out .class
rlm@10 5166 files. This directory must be in the classpath for 'compile' to
rlm@10 5167 work.
rlm@10 5168
rlm@10 5169 Defaults to \"classes\""
rlm@10 5170 {:added "1.0"})
rlm@10 5171
rlm@10 5172 (add-doc-and-meta *compile-files*
rlm@10 5173 "Set to true when compiling files, false otherwise."
rlm@10 5174 {:added "1.0"})
rlm@10 5175
rlm@10 5176 (add-doc-and-meta *ns*
rlm@10 5177 "A clojure.lang.Namespace object representing the current namespace."
rlm@10 5178 {:added "1.0"})
rlm@10 5179
rlm@10 5180 (add-doc-and-meta *in*
rlm@10 5181 "A java.io.Reader object representing standard input for read operations.
rlm@10 5182
rlm@10 5183 Defaults to System/in, wrapped in a LineNumberingPushbackReader"
rlm@10 5184 {:added "1.0"})
rlm@10 5185
rlm@10 5186 (add-doc-and-meta *out*
rlm@10 5187 "A java.io.Writer object representing standard output for print operations.
rlm@10 5188
rlm@10 5189 Defaults to System/out"
rlm@10 5190 {:added "1.0"})
rlm@10 5191
rlm@10 5192 (add-doc-and-meta *err*
rlm@10 5193 "A java.io.Writer object representing standard error for print operations.
rlm@10 5194
rlm@10 5195 Defaults to System/err, wrapped in a PrintWriter"
rlm@10 5196 {:added "1.0"})
rlm@10 5197
rlm@10 5198 (add-doc-and-meta *flush-on-newline*
rlm@10 5199 "When set to true, output will be flushed whenever a newline is printed.
rlm@10 5200
rlm@10 5201 Defaults to true."
rlm@10 5202 {:added "1.0"})
rlm@10 5203
rlm@10 5204 (add-doc-and-meta *print-meta*
rlm@10 5205 "If set to logical true, when printing an object, its metadata will also
rlm@10 5206 be printed in a form that can be read back by the reader.
rlm@10 5207
rlm@10 5208 Defaults to false."
rlm@10 5209 {:added "1.0"})
rlm@10 5210
rlm@10 5211 (add-doc-and-meta *print-dup*
rlm@10 5212 "When set to logical true, objects will be printed in a way that preserves
rlm@10 5213 their type when read in later.
rlm@10 5214
rlm@10 5215 Defaults to false."
rlm@10 5216 {:added "1.0"})
rlm@10 5217
rlm@10 5218 (add-doc-and-meta *print-readably*
rlm@10 5219 "When set to logical false, strings and characters will be printed with
rlm@10 5220 non-alphanumeric characters converted to the appropriate escape sequences.
rlm@10 5221
rlm@10 5222 Defaults to true"
rlm@10 5223 {:added "1.0"})
rlm@10 5224
rlm@10 5225 (add-doc-and-meta *read-eval*
rlm@10 5226 "When set to logical false, the EvalReader (#=(...)) is disabled in the
rlm@10 5227 read/load in the thread-local binding.
rlm@10 5228 Example: (binding [*read-eval* false] (read-string \"#=(eval (def x 3))\"))
rlm@10 5229
rlm@10 5230 Defaults to true"
rlm@10 5231 {:added "1.0"})
rlm@10 5232
rlm@10 5233 (defn future?
rlm@10 5234 "Returns true if x is a future"
rlm@10 5235 {:added "1.1"}
rlm@10 5236 [x] (instance? java.util.concurrent.Future x))
rlm@10 5237
rlm@10 5238 (defn future-done?
rlm@10 5239 "Returns true if future f is done"
rlm@10 5240 {:added "1.1"}
rlm@10 5241 [^java.util.concurrent.Future f] (.isDone f))
rlm@10 5242
rlm@10 5243
rlm@10 5244 (defmacro letfn
rlm@10 5245 "Takes a vector of function specs and a body, and generates a set of
rlm@10 5246 bindings of functions to their names. All of the names are available
rlm@10 5247 in all of the definitions of the functions, as well as the body.
rlm@10 5248
rlm@10 5249 fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+)"
rlm@10 5250 {:added "1.0"}
rlm@10 5251 [fnspecs & body]
rlm@10 5252 `(letfn* ~(vec (interleave (map first fnspecs)
rlm@10 5253 (map #(cons `fn %) fnspecs)))
rlm@10 5254 ~@body))
rlm@10 5255
rlm@10 5256
rlm@10 5257 ;;;;;;; case ;;;;;;;;;;;;;
rlm@10 5258 (defn- shift-mask [shift mask x]
rlm@10 5259 (-> x (bit-shift-right shift) (bit-and mask)))
rlm@10 5260
rlm@10 5261 (defn- min-hash
rlm@10 5262 "takes a collection of keys and returns [shift mask]"
rlm@10 5263 [keys]
rlm@10 5264 (let [hashes (map hash keys)
rlm@10 5265 cnt (count keys)]
rlm@10 5266 (when-not (apply distinct? hashes)
rlm@10 5267 (throw (IllegalArgumentException. "Hashes must be distinct")))
rlm@10 5268 (or (first
rlm@10 5269 (filter (fn [[s m]]
rlm@10 5270 (apply distinct? (map #(shift-mask s m %) hashes)))
rlm@10 5271 (for [mask (map #(dec (bit-shift-left 1 %)) (range 1 14))
rlm@10 5272 shift (range 0 31)]
rlm@10 5273 [shift mask])))
rlm@10 5274 (throw (IllegalArgumentException. "No distinct mapping found")))))
rlm@10 5275
rlm@10 5276 (defmacro case
rlm@10 5277 "Takes an expression, and a set of clauses.
rlm@10 5278
rlm@10 5279 Each clause can take the form of either:
rlm@10 5280
rlm@10 5281 test-constant result-expr
rlm@10 5282
rlm@10 5283 (test-constant1 ... test-constantN) result-expr
rlm@10 5284
rlm@10 5285 The test-constants are not evaluated. They must be compile-time
rlm@10 5286 literals, and need not be quoted. If the expression is equal to a
rlm@10 5287 test-constant, the corresponding result-expr is returned. A single
rlm@10 5288 default expression can follow the clauses, and its value will be
rlm@10 5289 returned if no clause matches. If no default expression is provided
rlm@10 5290 and no clause matches, an IllegalArgumentException is thrown.
rlm@10 5291
rlm@10 5292 Unlike cond and condp, case does a constant-time dispatch, the
rlm@10 5293 clauses are not considered sequentially. All manner of constant
rlm@10 5294 expressions are acceptable in case, including numbers, strings,
rlm@10 5295 symbols, keywords, and (Clojure) composites thereof. Note that since
rlm@10 5296 lists are used to group multiple constants that map to the same
rlm@10 5297 expression, a vector can be used to match a list if needed. The
rlm@10 5298 test-constants need not be all of the same type."
rlm@10 5299 {:added "1.2"}
rlm@10 5300
rlm@10 5301 [e & clauses]
rlm@10 5302 (let [ge (with-meta (gensym) {:tag Object})
rlm@10 5303 default (if (odd? (count clauses))
rlm@10 5304 (last clauses)
rlm@10 5305 `(throw (IllegalArgumentException. (str "No matching clause: " ~ge))))
rlm@10 5306 cases (partition 2 clauses)
rlm@10 5307 case-map (reduce (fn [m [test expr]]
rlm@10 5308 (if (seq? test)
rlm@10 5309 (into m (zipmap test (repeat expr)))
rlm@10 5310 (assoc m test expr)))
rlm@10 5311 {} cases)
rlm@10 5312 [shift mask] (if (seq case-map) (min-hash (keys case-map)) [0 0])
rlm@10 5313
rlm@10 5314 hmap (reduce (fn [m [test expr :as te]]
rlm@10 5315 (assoc m (shift-mask shift mask (hash test)) te))
rlm@10 5316 (sorted-map) case-map)]
rlm@10 5317 `(let [~ge ~e]
rlm@10 5318 ~(condp = (count clauses)
rlm@10 5319 0 default
rlm@10 5320 1 default
rlm@10 5321 `(case* ~ge ~shift ~mask ~(key (first hmap)) ~(key (last hmap)) ~default ~hmap
rlm@10 5322 ~(every? keyword? (keys case-map)))))))
rlm@10 5323
rlm@10 5324 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; helper files ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
rlm@10 5325 (alter-meta! (find-ns 'clojure.core) assoc :doc "Fundamental library of the Clojure language")
rlm@10 5326 (load "core_proxy")
rlm@10 5327 (load "core_print")
rlm@10 5328 (load "genclass")
rlm@10 5329 (load "core_deftype")
rlm@10 5330 (load "core/protocols")
rlm@10 5331 (load "gvec")
rlm@10 5332
rlm@10 5333 ;; redefine reduce with internal-reduce
rlm@10 5334 #_(defn reduce
rlm@10 5335 "f should be a function of 2 arguments. If val is not supplied,
rlm@10 5336 returns the result of applying f to the first 2 items in coll, then
rlm@10 5337 applying f to that result and the 3rd item, etc. If coll contains no
rlm@10 5338 items, f must accept no arguments as well, and reduce returns the
rlm@10 5339 result of calling f with no arguments. If coll has only 1 item, it
rlm@10 5340 is returned and f is not called. If val is supplied, returns the
rlm@10 5341 result of applying f to val and the first item in coll, then
rlm@10 5342 applying f to that result and the 2nd item, etc. If coll contains no
rlm@10 5343 items, returns val and f is not called."
rlm@10 5344 {:added "1.0"}
rlm@10 5345 ([f coll]
rlm@10 5346 (if-let [s (seq coll)]
rlm@10 5347 (reduce f (first s) (next s))
rlm@10 5348 (f)))
rlm@10 5349 ([f val coll]
rlm@10 5350 (let [s (seq coll)]
rlm@10 5351 (clojure.core.protocols/internal-reduce s f val))))
rlm@10 5352
rlm@10 5353 (require '[clojure.java.io :as jio])
rlm@10 5354
rlm@10 5355 (defn- normalize-slurp-opts
rlm@10 5356 [opts]
rlm@10 5357 (if (string? (first opts))
rlm@10 5358 (do
rlm@10 5359 (println "WARNING: (slurp f enc) is deprecated, use (slurp f :encoding enc).")
rlm@10 5360 [:encoding (first opts)])
rlm@10 5361 opts))
rlm@10 5362
rlm@10 5363 (defn slurp
rlm@10 5364 "Reads the file named by f using the encoding enc into a string
rlm@10 5365 and returns it."
rlm@10 5366 {:added "1.0"}
rlm@10 5367 ([f & opts]
rlm@10 5368 (let [opts (normalize-slurp-opts opts)
rlm@10 5369 sb (StringBuilder.)]
rlm@10 5370 (with-open [#^java.io.Reader r (apply jio/reader f opts)]
rlm@10 5371 (loop [c (.read r)]
rlm@10 5372 (if (neg? c)
rlm@10 5373 (str sb)
rlm@10 5374 (do
rlm@10 5375 (.append sb (char c))
rlm@10 5376 (recur (.read r)))))))))
rlm@10 5377
rlm@10 5378 (defn spit
rlm@10 5379 "Opposite of slurp. Opens f with writer, writes content, then
rlm@10 5380 closes f. Options passed to clojure.java.io/writer."
rlm@10 5381 {:added "1.2"}
rlm@10 5382 [f content & options]
rlm@10 5383 (with-open [#^java.io.Writer w (apply jio/writer f options)]
rlm@10 5384 (.write w (str content))))
rlm@10 5385
rlm@10 5386 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; futures (needs proxy);;;;;;;;;;;;;;;;;;
rlm@10 5387 (defn future-call
rlm@10 5388 "Takes a function of no args and yields a future object that will
rlm@10 5389 invoke the function in another thread, and will cache the result and
rlm@10 5390 return it on all subsequent calls to deref/@. If the computation has
rlm@10 5391 not yet finished, calls to deref/@ will block."
rlm@10 5392 {:added "1.1"}
rlm@10 5393 [^Callable f]
rlm@10 5394 (let [fut (.submit clojure.lang.Agent/soloExecutor f)]
rlm@10 5395 (reify
rlm@10 5396 clojure.lang.IDeref
rlm@10 5397 (deref [_] (.get fut))
rlm@10 5398 java.util.concurrent.Future
rlm@10 5399 (get [_] (.get fut))
rlm@10 5400 (get [_ timeout unit] (.get fut timeout unit))
rlm@10 5401 (isCancelled [_] (.isCancelled fut))
rlm@10 5402 (isDone [_] (.isDone fut))
rlm@10 5403 (cancel [_ interrupt?] (.cancel fut interrupt?)))))
rlm@10 5404
rlm@10 5405 (defmacro future
rlm@10 5406 "Takes a body of expressions and yields a future object that will
rlm@10 5407 invoke the body in another thread, and will cache the result and
rlm@10 5408 return it on all subsequent calls to deref/@. If the computation has
rlm@10 5409 not yet finished, calls to deref/@ will block."
rlm@10 5410 {:added "1.1"}
rlm@10 5411 [& body] `(future-call (^{:once true} fn* [] ~@body)))
rlm@10 5412
rlm@10 5413
rlm@10 5414 (defn future-cancel
rlm@10 5415 "Cancels the future, if possible."
rlm@10 5416 {:added "1.1"}
rlm@10 5417 [^java.util.concurrent.Future f] (.cancel f true))
rlm@10 5418
rlm@10 5419 (defn future-cancelled?
rlm@10 5420 "Returns true if future f is cancelled"
rlm@10 5421 {:added "1.1"}
rlm@10 5422 [^java.util.concurrent.Future f] (.isCancelled f))
rlm@10 5423
rlm@10 5424 (defn pmap
rlm@10 5425 "Like map, except f is applied in parallel. Semi-lazy in that the
rlm@10 5426 parallel computation stays ahead of the consumption, but doesn't
rlm@10 5427 realize the entire result unless required. Only useful for
rlm@10 5428 computationally intensive functions where the time of f dominates
rlm@10 5429 the coordination overhead."
rlm@10 5430 {:added "1.0"}
rlm@10 5431 ([f coll]
rlm@10 5432 (let [n (+ 2 (.. Runtime getRuntime availableProcessors))
rlm@10 5433 rets (map #(future (f %)) coll)
rlm@10 5434 step (fn step [[x & xs :as vs] fs]
rlm@10 5435 (lazy-seq
rlm@10 5436 (if-let [s (seq fs)]
rlm@10 5437 (cons (deref x) (step xs (rest s)))
rlm@10 5438 (map deref vs))))]
rlm@10 5439 (step rets (drop n rets))))
rlm@10 5440 ([f coll & colls]
rlm@10 5441 (let [step (fn step [cs]
rlm@10 5442 (lazy-seq
rlm@10 5443 (let [ss (map seq cs)]
rlm@10 5444 (when (every? identity ss)
rlm@10 5445 (cons (map first ss) (step (map rest ss)))))))]
rlm@10 5446 (pmap #(apply f %) (step (cons coll colls))))))
rlm@10 5447
rlm@10 5448 (defn pcalls
rlm@10 5449 "Executes the no-arg fns in parallel, returning a lazy sequence of
rlm@10 5450 their values"
rlm@10 5451 {:added "1.0"}
rlm@10 5452 [& fns] (pmap #(%) fns))
rlm@10 5453
rlm@10 5454 (defmacro pvalues
rlm@10 5455 "Returns a lazy sequence of the values of the exprs, which are
rlm@10 5456 evaluated in parallel"
rlm@10 5457 {:added "1.0"}
rlm@10 5458 [& exprs]
rlm@10 5459 `(pcalls ~@(map #(list `fn [] %) exprs)))
rlm@10 5460
rlm@10 5461
rlm@10 5462 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; clojure version number ;;;;;;;;;;;;;;;;;;;;;;
rlm@10 5463
rlm@10 5464 (let [version-stream (.getResourceAsStream (clojure.lang.RT/baseLoader)
rlm@10 5465 "clojure/version.properties")
rlm@10 5466 properties (doto (new java.util.Properties) (.load version-stream))
rlm@10 5467 prop (fn [k] (.getProperty properties (str "clojure.version." k)))
rlm@10 5468 clojure-version {:major (Integer/valueOf ^String (prop "major"))
rlm@10 5469 :minor (Integer/valueOf ^String (prop "minor"))
rlm@10 5470 :incremental (Integer/valueOf ^String (prop "incremental"))
rlm@10 5471 :qualifier (prop "qualifier")}]
rlm@10 5472 (def *clojure-version*
rlm@10 5473 (if (not (= (prop "interim") "false"))
rlm@10 5474 (clojure.lang.RT/assoc clojure-version :interim true)
rlm@10 5475 clojure-version)))
rlm@10 5476
rlm@10 5477 (add-doc-and-meta *clojure-version*
rlm@10 5478 "The version info for Clojure core, as a map containing :major :minor
rlm@10 5479 :incremental and :qualifier keys. Feature releases may increment
rlm@10 5480 :minor and/or :major, bugfix releases will increment :incremental.
rlm@10 5481 Possible values of :qualifier include \"GA\", \"SNAPSHOT\", \"RC-x\" \"BETA-x\""
rlm@10 5482 {:added "1.0"})
rlm@10 5483
rlm@10 5484 (defn
rlm@10 5485 clojure-version
rlm@10 5486 "Returns clojure version as a printable string."
rlm@10 5487 {:added "1.0"}
rlm@10 5488 []
rlm@10 5489 (str (:major *clojure-version*)
rlm@10 5490 "."
rlm@10 5491 (:minor *clojure-version*)
rlm@10 5492 (when-let [i (:incremental *clojure-version*)]
rlm@10 5493 (str "." i))
rlm@10 5494 (when-let [q (:qualifier *clojure-version*)]
rlm@10 5495 (when (pos? (count q)) (str "-" q)))
rlm@10 5496 (when (:interim *clojure-version*)
rlm@10 5497 "-SNAPSHOT")))
rlm@10 5498
rlm@10 5499 (defn promise
rlm@10 5500 "Alpha - subject to change.
rlm@10 5501 Returns a promise object that can be read with deref/@, and set,
rlm@10 5502 once only, with deliver. Calls to deref/@ prior to delivery will
rlm@10 5503 block. All subsequent derefs will return the same delivered value
rlm@10 5504 without blocking."
rlm@10 5505 {:added "1.1"}
rlm@10 5506 []
rlm@10 5507 (let [d (java.util.concurrent.CountDownLatch. 1)
rlm@10 5508 v (atom nil)]
rlm@10 5509 (reify
rlm@10 5510 clojure.lang.IDeref
rlm@10 5511 (deref [_] (.await d) @v)
rlm@10 5512 clojure.lang.IFn
rlm@10 5513 (invoke [this x]
rlm@10 5514 (locking d
rlm@10 5515 (if (pos? (.getCount d))
rlm@10 5516 (do (reset! v x)
rlm@10 5517 (.countDown d)
rlm@10 5518 this)
rlm@10 5519 (throw (IllegalStateException. "Multiple deliver calls to a promise"))))))))
rlm@10 5520
rlm@10 5521 (defn deliver
rlm@10 5522 "Alpha - subject to change.
rlm@10 5523 Delivers the supplied value to the promise, releasing any pending
rlm@10 5524 derefs. A subsequent call to deliver on a promise will throw an exception."
rlm@10 5525 {:added "1.1"}
rlm@10 5526 [promise val] (promise val))
rlm@10 5527
rlm@10 5528
rlm@10 5529
rlm@10 5530 (defn flatten
rlm@10 5531 "Takes any nested combination of sequential things (lists, vectors,
rlm@10 5532 etc.) and returns their contents as a single, flat sequence.
rlm@10 5533 (flatten nil) returns nil."
rlm@10 5534 {:added "1.2"}
rlm@10 5535 [x]
rlm@10 5536 (filter (complement sequential?)
rlm@10 5537 (rest (tree-seq sequential? seq x))))
rlm@10 5538
rlm@10 5539 (defn group-by
rlm@10 5540 "Returns a map of the elements of coll keyed by the result of
rlm@10 5541 f on each element. The value at each key will be a vector of the
rlm@10 5542 corresponding elements, in the order they appeared in coll."
rlm@10 5543 {:added "1.2"}
rlm@10 5544 [f coll]
rlm@10 5545 (persistent!
rlm@10 5546 (reduce
rlm@10 5547 (fn [ret x]
rlm@10 5548 (let [k (f x)]
rlm@10 5549 (assoc! ret k (conj (get ret k []) x))))
rlm@10 5550 (transient {}) coll)))
rlm@10 5551
rlm@10 5552 (defn partition-by
rlm@10 5553 "Applies f to each value in coll, splitting it each time f returns
rlm@10 5554 a new value. Returns a lazy seq of partitions."
rlm@10 5555 {:added "1.2"}
rlm@10 5556 [f coll]
rlm@10 5557 (lazy-seq
rlm@10 5558 (when-let [s (seq coll)]
rlm@10 5559 (let [fst (first s)
rlm@10 5560 fv (f fst)
rlm@10 5561 run (cons fst (take-while #(= fv (f %)) (rest s)))]
rlm@10 5562 (cons run (partition-by f (drop (count run) s)))))))
rlm@10 5563
rlm@10 5564 (defn frequencies
rlm@10 5565 "Returns a map from distinct items in coll to the number of times
rlm@10 5566 they appear."
rlm@10 5567 {:added "1.2"}
rlm@10 5568 [coll]
rlm@10 5569 (persistent!
rlm@10 5570 (reduce (fn [counts x]
rlm@10 5571 (assoc! counts x (inc (get counts x 0))))
rlm@10 5572 (transient {}) coll)))
rlm@10 5573
rlm@10 5574 (defn reductions
rlm@10 5575 "Returns a lazy seq of the intermediate values of the reduction (as
rlm@10 5576 per reduce) of coll by f, starting with init."
rlm@10 5577 {:added "1.2"}
rlm@10 5578 ([f coll]
rlm@10 5579 (lazy-seq
rlm@10 5580 (if-let [s (seq coll)]
rlm@10 5581 (reductions f (first s) (rest s))
rlm@10 5582 (list (f)))))
rlm@10 5583 ([f init coll]
rlm@10 5584 (cons init
rlm@10 5585 (lazy-seq
rlm@10 5586 (when-let [s (seq coll)]
rlm@10 5587 (reductions f (f init (first s)) (rest s)))))))
rlm@10 5588
rlm@10 5589 (defn rand-nth
rlm@10 5590 "Return a random element of the (sequential) collection. Will have
rlm@10 5591 the same performance characteristics as nth for the given
rlm@10 5592 collection."
rlm@10 5593 {:added "1.2"}
rlm@10 5594 [coll]
rlm@10 5595 (nth coll (rand-int (count coll))))
rlm@10 5596
rlm@10 5597 (defn partition-all
rlm@10 5598 "Returns a lazy sequence of lists like partition, but may include
rlm@10 5599 partitions with fewer than n items at the end."
rlm@10 5600 {:added "1.2"}
rlm@10 5601 ([n coll]
rlm@10 5602 (partition-all n n coll))
rlm@10 5603 ([n step coll]
rlm@10 5604 (lazy-seq
rlm@10 5605 (when-let [s (seq coll)]
rlm@10 5606 (cons (take n s) (partition-all n step (drop step s)))))))
rlm@10 5607
rlm@10 5608 (defn shuffle
rlm@10 5609 "Return a random permutation of coll"
rlm@10 5610 {:added "1.2"}
rlm@10 5611 [coll]
rlm@10 5612 (let [al (java.util.ArrayList. coll)]
rlm@10 5613 (java.util.Collections/shuffle al)
rlm@10 5614 (clojure.lang.RT/vector (.toArray al))))
rlm@10 5615
rlm@10 5616 (defn map-indexed
rlm@10 5617 "Returns a lazy sequence consisting of the result of applying f to 0
rlm@10 5618 and the first item of coll, followed by applying f to 1 and the second
rlm@10 5619 item in coll, etc, until coll is exhausted. Thus function f should
rlm@10 5620 accept 2 arguments, index and item."
rlm@10 5621 {:added "1.2"}
rlm@10 5622 [f coll]
rlm@10 5623 (letfn [(mapi [idx coll]
rlm@10 5624 (lazy-seq
rlm@10 5625 (when-let [s (seq coll)]
rlm@10 5626 (if (chunked-seq? s)
rlm@10 5627 (let [c (chunk-first s)
rlm@10 5628 size (int (count c))
rlm@10 5629 b (chunk-buffer size)]
rlm@10 5630 (dotimes [i size]
rlm@10 5631 (chunk-append b (f (+ idx i) (.nth c i))))
rlm@10 5632 (chunk-cons (chunk b) (mapi (+ idx size) (chunk-rest s))))
rlm@10 5633 (cons (f idx (first s)) (mapi (inc idx) (rest s)))))))]
rlm@10 5634 (mapi 0 coll)))
rlm@10 5635
rlm@10 5636 (defn keep
rlm@10 5637 "Returns a lazy sequence of the non-nil results of (f item). Note,
rlm@10 5638 this means false return values will be included. f must be free of
rlm@10 5639 side-effects."
rlm@10 5640 {:added "1.2"}
rlm@10 5641 ([f coll]
rlm@10 5642 (lazy-seq
rlm@10 5643 (when-let [s (seq coll)]
rlm@10 5644 (if (chunked-seq? s)
rlm@10 5645 (let [c (chunk-first s)
rlm@10 5646 size (count c)
rlm@10 5647 b (chunk-buffer size)]
rlm@10 5648 (dotimes [i size]
rlm@10 5649 (let [x (f (.nth c i))]
rlm@10 5650 (when-not (nil? x)
rlm@10 5651 (chunk-append b x))))
rlm@10 5652 (chunk-cons (chunk b) (keep f (chunk-rest s))))
rlm@10 5653 (let [x (f (first s))]
rlm@10 5654 (if (nil? x)
rlm@10 5655 (keep f (rest s))
rlm@10 5656 (cons x (keep f (rest s))))))))))
rlm@10 5657
rlm@10 5658 (defn keep-indexed
rlm@10 5659 "Returns a lazy sequence of the non-nil results of (f index item). Note,
rlm@10 5660 this means false return values will be included. f must be free of
rlm@10 5661 side-effects."
rlm@10 5662 {:added "1.2"}
rlm@10 5663 ([f coll]
rlm@10 5664 (letfn [(keepi [idx coll]
rlm@10 5665 (lazy-seq
rlm@10 5666 (when-let [s (seq coll)]
rlm@10 5667 (if (chunked-seq? s)
rlm@10 5668 (let [c (chunk-first s)
rlm@10 5669 size (count c)
rlm@10 5670 b (chunk-buffer size)]
rlm@10 5671 (dotimes [i size]
rlm@10 5672 (let [x (f (+ idx i) (.nth c i))]
rlm@10 5673 (when-not (nil? x)
rlm@10 5674 (chunk-append b x))))
rlm@10 5675 (chunk-cons (chunk b) (keepi (+ idx size) (chunk-rest s))))
rlm@10 5676 (let [x (f idx (first s))]
rlm@10 5677 (if (nil? x)
rlm@10 5678 (keepi (inc idx) (rest s))
rlm@10 5679 (cons x (keepi (inc idx) (rest s)))))))))]
rlm@10 5680 (keepi 0 coll))))
rlm@10 5681
rlm@10 5682 (defn fnil
rlm@10 5683 "Takes a function f, and returns a function that calls f, replacing
rlm@10 5684 a nil first argument to f with the supplied value x. Higher arity
rlm@10 5685 versions can replace arguments in the second and third
rlm@10 5686 positions (y, z). Note that the function f can take any number of
rlm@10 5687 arguments, not just the one(s) being nil-patched."
rlm@10 5688 {:added "1.2"}
rlm@10 5689 ([f x]
rlm@10 5690 (fn
rlm@10 5691 ([a] (f (if (nil? a) x a)))
rlm@10 5692 ([a b] (f (if (nil? a) x a) b))
rlm@10 5693 ([a b c] (f (if (nil? a) x a) b c))
rlm@10 5694 ([a b c & ds] (apply f (if (nil? a) x a) b c ds))))
rlm@10 5695 ([f x y]
rlm@10 5696 (fn
rlm@10 5697 ([a b] (f (if (nil? a) x a) (if (nil? b) y b)))
rlm@10 5698 ([a b c] (f (if (nil? a) x a) (if (nil? b) y b) c))
rlm@10 5699 ([a b c & ds] (apply f (if (nil? a) x a) (if (nil? b) y b) c ds))))
rlm@10 5700 ([f x y z]
rlm@10 5701 (fn
rlm@10 5702 ([a b] (f (if (nil? a) x a) (if (nil? b) y b)))
rlm@10 5703 ([a b c] (f (if (nil? a) x a) (if (nil? b) y b) (if (nil? c) z c)))
rlm@10 5704 ([a b c & ds] (apply f (if (nil? a) x a) (if (nil? b) y b) (if (nil? c) z c) ds)))))
rlm@10 5705
rlm@10 5706 (defn- ^{:dynamic true} assert-valid-fdecl
rlm@10 5707 "A good fdecl looks like (([a] ...) ([a b] ...)) near the end of defn."
rlm@10 5708 [fdecl]
rlm@10 5709 (if-let [bad-args (seq (remove #(vector? %) (map first fdecl)))]
rlm@10 5710 (throw (IllegalArgumentException. (str "Parameter declaration " (first bad-args) " should be a vector")))))