summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-07-29 16:46:44 +0000
committerRich Hickey <richhickey@gmail.com>2008-07-29 16:46:44 +0000
commitd59defe96831815c8d82f872c90ac14d75249a7f (patch)
tree13743c65aee6659ee6ec78427b1d7a3361107696 /src
parenta8bad60e1e27d2f5615d16a76bdb0cce783177b0 (diff)
moved clj files into src/clj/
Diffstat (limited to 'src')
-rw-r--r--src/clj/clojure/boot.clj2863
-rw-r--r--src/clj/clojure/genclass.clj520
-rw-r--r--src/clj/clojure/inspector/inspector.clj110
-rw-r--r--src/clj/clojure/parallel/parallel.clj249
-rw-r--r--src/clj/clojure/proxy.clj307
-rw-r--r--src/clj/clojure/set/set.clj116
-rw-r--r--src/clj/clojure/xml/xml.clj117
-rw-r--r--src/clj/clojure/zip/zip.clj248
8 files changed, 4530 insertions, 0 deletions
diff --git a/src/clj/clojure/boot.clj b/src/clj/clojure/boot.clj
new file mode 100644
index 00000000..6dcbc1e3
--- /dev/null
+++ b/src/clj/clojure/boot.clj
@@ -0,0 +1,2863 @@
+; Copyright (c) Rich Hickey. All rights reserved.
+; The use and distribution terms for this software are covered by the
+; Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+; which can be found in the file CPL.TXT at the root of this distribution.
+; By using this software in any fashion, you are agreeing to be bound by
+; the terms of this license.
+; You must not remove this notice, or any other, from this software.
+
+(in-ns 'clojure)
+
+(def
+ #^{:arglists '([& items])
+ :doc "Creates a new list containing the items."}
+ list (. clojure.lang.PersistentList creator))
+
+(def
+ #^{:arglists '([x seq])
+ :doc "Returns a new seq where x is the first element and seq is
+ the rest."}
+
+ cons (fn* cons [x seq] (. clojure.lang.RT (cons x seq))))
+
+;during bootstrap we don't have destructuring let, loop or fn, will redefine later
+(def
+ #^{:macro true}
+ let (fn* let [& decl] (cons 'let* decl)))
+
+(def
+ #^{:macro true}
+ loop (fn* loop [& decl] (cons 'loop* decl)))
+
+(def
+ #^{:macro true}
+ fn (fn* fn [& decl] (cons 'fn* decl)))
+
+(def
+ #^{:arglists '([coll])
+ :doc "Returns the first item in the collection. Calls seq on its
+ argument. If coll is nil, returns nil."}
+ first (fn first [coll] (. clojure.lang.RT (first coll))))
+
+(def
+ #^{:arglists '([coll])
+ :doc "Returns a seq of the items after the first. Calls seq on its
+ argument. If there are no more items, returns nil."}
+ rest (fn rest [x] (. clojure.lang.RT (rest x))))
+
+(def
+ #^{:arglists '([coll x] [coll x & xs])
+ :doc "conj[oin]. Returns a new collection with the xs
+ 'added'. (conj nil item) returns (item). The 'addition' may
+ happen at different 'places' depending on the concrete type."}
+ conj (fn conj
+ ([coll x] (. clojure.lang.RT (conj coll x)))
+ ([coll x & xs]
+ (if xs
+ (recur (conj coll x) (first xs) (rest xs))
+ (conj coll x)))))
+
+(def
+ #^{:doc "Same as (first (rest x))"
+ :arglists '([x])}
+ second (fn second [x] (first (rest x))))
+
+(def
+ #^{:doc "Same as (first (first x))"
+ :arglists '([x])}
+ ffirst (fn ffirst [x] (first (first x))))
+
+(def
+ #^{:doc "Same as (rest (first x))"
+ :arglists '([x])}
+ rfirst (fn rfirst [x] (rest (first x))))
+
+(def
+ #^{:doc "Same as (first (rest x))"
+ :arglists '([x])}
+ frest (fn frest [x] (first (rest x))))
+
+(def
+ #^{:doc "Same as (rest (rest x))"
+ :arglists '([x])}
+ rrest (fn rrest [x] (rest (rest x))))
+
+(def
+ #^{:arglists '([coll])
+ :doc "Sequence. Returns a new ISeq on the collection. If the
+ collection is empty, returns nil. (seq nil) returns nil. seq also
+ works on Strings, native Java arrays (of reference types) and any
+ objects that implement Iterable."
+ :tag clojure.lang.ISeq}
+ seq (fn seq [coll] (. clojure.lang.RT (seq coll))))
+
+(def
+ #^{:arglists '([#^Class c x])
+ :doc "Evaluates x and tests if it is an instance of the class
+ c. Returns true or false"}
+ instance? (fn instance? [#^Class c x] (. c (isInstance x))))
+
+(def
+ #^{:arglists '([x])
+ :doc "Return true if x implements ISeq"}
+ seq? (fn seq? [x] (instance? clojure.lang.ISeq x)))
+
+(def
+ #^{:arglists '([x])
+ :doc "Return true if x is a String"}
+ string? (fn string? [x] (instance? String x)))
+
+(def
+ #^{:arglists '([x])
+ :doc "Return true if x implements IPersistentMap"}
+ map? (fn map? [x] (instance? clojure.lang.IPersistentMap x)))
+
+(def
+ #^{:arglists '([x])
+ :doc "Return true if x implements IPersistentVector "}
+ vector? (fn vector? [x] (instance? clojure.lang.IPersistentVector x)))
+
+(def
+ #^{:private true}
+ sigs
+ (fn [fdecl]
+ (if (seq? (first fdecl))
+ (loop [ret [] fdecl fdecl]
+ (if fdecl
+ (recur (conj ret (first (first fdecl))) (rest fdecl))
+ (seq ret)))
+ (list (first fdecl)))))
+
+(def
+ #^{:arglists '([map key val] [map key val & kvs])
+ :doc "assoc[iate]. When applied to a map, returns a new map of the
+ same (hashed/sorted) type, that contains the mapping of key(s) to
+ val(s). When applied to a vector, returns a new vector that
+ contains val at index. Note - index must be <= (count vector)."}
+ assoc
+ (fn assoc
+ ([map key val] (. clojure.lang.RT (assoc map key val)))
+ ([map key val & kvs]
+ (let [ret (assoc map key val)]
+ (if kvs
+ (recur ret (first kvs) (second kvs) (rrest kvs))
+ ret)))))
+
+;;;;;;;;;;;;;;;;; metadata ;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(def
+ #^{:arglists '([obj])
+ :doc "Returns the metadata of obj, returns nil if there is no metadata."}
+ meta (fn meta [x]
+ (if (instance? clojure.lang.IObj x)
+ (. #^clojure.lang.IObj x (meta)))))
+
+(def
+ #^{:arglists '([#^clojure.lang.IObj obj m])
+ :doc "Returns an object of the same type and value as obj, with
+ map m as its metadata."}
+ with-meta (fn with-meta [#^clojure.lang.IObj x m]
+ (. x (withMeta m))))
+
+(def
+ #^{:arglists '([coll])
+ :doc "Return the last item in coll, in linear time"}
+ last (fn last [s]
+ (if (rest s)
+ (recur (rest s))
+ (first s))))
+
+(def
+ #^{:arglists '([coll])
+ :doc "Return a sequence of all but the last item in coll, in linear time"}
+ butlast (fn butlast [s]
+ (loop [ret [] s s]
+ (if (rest s)
+ (recur (conj ret (first s)) (rest s))
+ (seq ret)))))
+
+(def
+
+ #^{:doc "Same as (def name (fn [params* ] exprs*)) or (def
+ name (fn ([params* ] exprs*)+)) with any doc-string or attrs added
+ to the var metadata"
+ :arglists '([name doc-string? attr-map? [params*] body]
+ [name doc-string? attr-map? ([params*] body)+ attr-map?])}
+ defn (fn defn [name & fdecl]
+ (let [m (if (string? (first fdecl))
+ {:doc (first fdecl)}
+ {})
+ fdecl (if (string? (first fdecl))
+ (rest fdecl)
+ fdecl)
+ m (if (map? (first fdecl))
+ (conj m (first fdecl))
+ m)
+ fdecl (if (map? (first fdecl))
+ (rest fdecl)
+ fdecl)
+ fdecl (if (vector? (first fdecl))
+ (list fdecl)
+ fdecl)
+ m (if (map? (last fdecl))
+ (conj m (last fdecl))
+ m)
+ fdecl (if (map? (last fdecl))
+ (butlast fdecl)
+ fdecl)
+ m (conj {:arglists (list 'quote (sigs fdecl))} m)]
+ (list 'def (with-meta name (conj (if (meta name) (meta name) {}) m))
+ (cons `fn fdecl)))))
+
+(. (var defn) (setMacro))
+
+(defn cast
+ "Throws a ClassCastException if x is not a c, else returns x."
+ [#^Class c x]
+ (. c (cast x)))
+
+(defn to-array
+ "Returns an array of Objects containing the contents of coll, which
+ can be any Collection. Maps to java.util.Collection.toArray()."
+ [coll] (. clojure.lang.RT (toArray coll)))
+
+(defn vector
+ "Creates a new vector containing the args."
+ ([] [])
+ ([& args]
+ (. clojure.lang.LazilyPersistentVector (create args))))
+
+(defn vec
+ "Creates a new vector containing the contents of coll."
+ ([coll]
+ (. clojure.lang.LazilyPersistentVector (createOwning (to-array coll)))))
+
+(defn hash-map
+ "keyval => key val
+ Returns a new hash map with supplied mappings."
+ ([] {})
+ ([& keyvals]
+ (. clojure.lang.PersistentHashMap (create keyvals))))
+
+(defn hash-set
+ "Returns a new hash set with supplied keys."
+ ([] #{})
+ ([& keys]
+ (. clojure.lang.PersistentHashSet (create keys))))
+
+(defn sorted-map
+ "keyval => key val
+ Returns a new sorted map with supplied mappings."
+ ([& keyvals]
+ (. clojure.lang.PersistentTreeMap (create keyvals))))
+
+(defn sorted-set
+ "Returns a new sorted set with supplied keys."
+ ([& keys]
+ (. clojure.lang.PersistentTreeSet (create keys))))
+
+(defn sorted-map-by
+ "keyval => key val
+ Returns a new sorted map with supplied mappings, using the supplied comparator."
+ ([comparator & keyvals]
+ (. clojure.lang.PersistentTreeMap (create comparator keyvals))))
+
+;;;;;;;;;;;;;;;;;;;;
+(def
+
+ #^{:doc "Like defn, but the resulting function name is declared as a
+ macro and will be used as a macro by the compiler when it is
+ called."
+ :arglists '([name doc-string? attr-map? [params*] body]
+ [name doc-string? attr-map? ([params*] body)+ attr-map?])}
+ defmacro (fn [name & args]
+ (list 'do
+ (cons `defn (cons name args))
+ (list '. (list 'var name) '(setMacro)))))
+
+(. (var defmacro) (setMacro))
+
+(defmacro when
+ "Evaluates test. If logical true, evaluates body in an implicit do."
+ [test & body]
+ (list 'if test (cons 'do body)))
+
+(defmacro when-not
+ "Evaluates test. If logical false, evaluates body in an implicit do."
+ [test & body]
+ (list 'if test nil (cons 'do body)))
+
+(defn nil?
+ "Returns true if x is nil, false otherwise."
+ {:tag Boolean}
+ [x] (identical? x nil))
+
+(defn false?
+ "Returns true if x is the value false, false otherwise."
+ {:tag Boolean}
+ [x] (identical? x false))
+
+(defn true?
+ "Returns true if x is the value true, false otherwise."
+ {:tag Boolean}
+ [x] (identical? x true))
+
+(defn not
+ "Returns true if x is logical false, false otherwise."
+ {:tag Boolean}
+ [x] (if x false true))
+
+(defn str
+ "With no args, returns the empty string. With one arg x, returns
+ x.toString(). (str nil) returns the empty string. With more than
+ one arg, returns the concatenation of the str values of the args."
+ {:tag String}
+ ([] "")
+ ([#^Object x]
+ (if (nil? x) "" (. x (toString))))
+ ([x & ys]
+ (loop [sb (new StringBuilder #^String (str x)) more ys]
+ (if more
+ (recur (. sb (append (str (first more)))) (rest more))
+ (str sb)))))
+
+(defn symbol
+ "Returns a Symbol with the given namespace and name."
+ ([name] (. clojure.lang.Symbol (intern name)))
+ ([ns name] (. clojure.lang.Symbol (intern ns name))))
+
+(defn keyword
+ "Returns a Keyword with the given namespace and name. Do not use :
+ in the keyword strings, it will be added automatically."
+ ([name] (. clojure.lang.Keyword (intern nil name)))
+ ([ns name] (. clojure.lang.Keyword (intern ns name))))
+
+(defn gensym
+ "Returns a new symbol with a unique name. If a prefix string is
+ supplied, the name is prefix# where # is some unique number. If
+ prefix is not supplied, the prefix is 'G'."
+ ([] (gensym "G__"))
+ ([prefix-string] (. clojure.lang.Symbol (intern (str prefix-string (str (. clojure.lang.RT (nextID))))))))
+
+(defmacro cond
+ "Takes a set of test/expr pairs. It evaluates each test one at a
+ time. If a test returns logical true, cond evaluates and returns
+ the value of the corresponding expr and doesn't evaluate any of the
+ other tests or exprs. (cond) returns nil."
+ [& clauses]
+ (when clauses
+ (list 'if (first clauses)
+ (second clauses)
+ (cons 'cond (rest (rest clauses))))))
+
+(defn spread
+ {:private true}
+ [arglist]
+ (cond
+ (nil? arglist) nil
+ (nil? (rest arglist)) (seq (first arglist))
+ :else (cons (first arglist) (spread (rest arglist)))))
+
+(defn apply
+ "Applies fn f to the argument list formed by prepending args to argseq."
+ {:arglists '([f args* argseq])}
+ [#^clojure.lang.IFn f & args]
+ (. f (applyTo (spread args))))
+
+(defn list*
+ "Creates a new list containing the item prepended to more."
+ [item & more]
+ (spread (cons item more)))
+
+(defmacro delay
+ "Takes a body of expressions and yields a function than will invoke
+ the body only the first time it is called, and will cache the result
+ and return it on all calls"
+ [& body]
+ (list 'new 'clojure.lang.Delay (list* `fn [] body)))
+
+(defn fnseq
+ "Returns a seq object whose first is first and whose rest is the
+ value produced by calling restfn with no arguments. restfn will be
+ called at most once per step in the sequence, e.g. calling rest
+ repeatedly on the head of the seq calls restfn once - the value it
+ yields is cached."
+ [first restfn]
+ (new clojure.lang.FnSeq first restfn))
+
+(defmacro lazy-cons
+ "Expands to code which produces a seq object whose first is
+ first-expr and whose rest is rest-expr, neither of which is
+ evaluated until first/rest is called. Each expr will be evaluated at most
+ once per step in the sequence, e.g. calling first/rest repeatedly on the
+ same node of the seq evaluates first/rest-expr once - the values they yield are
+ cached."
+ [first-expr & rest-expr]
+ (list 'new 'clojure.lang.LazySeq (list `fn [] first-expr) (list* `fn [] rest-expr)))
+
+(defn concat
+ "Returns a lazy seq representing the concatenation of the elements in x + xs."
+ ([] nil)
+ ([x & xs]
+ (cond
+ (nil? xs) (seq x)
+ (nil? (seq x)) (recur (first xs) (rest xs))
+ :else (lazy-cons (first x) (apply concat (rest x) xs)))))
+
+;;;;;;;;;;;;;;;;at this point all the support for syntax-quote exists;;;;;;;;;;;;;;;;;;;;;;
+(defn =
+ "Equality. Returns true if obj1 equals obj2, false if not. Same as
+ Java obj1.equals(obj2) except it also works for nil, and compares
+ numbers in a type-independent manner. Clojure's immutable data
+ structures define equals() (and thus =) as a value, not an identity,
+ comparison."
+ {:tag Boolean
+ :inline (fn [x y] `(. clojure.lang.Util equal ~x ~y))}
+ [x y] (. clojure.lang.Util (equal x y)))
+
+(defn not=
+ "Same as (not (= obj1 obj2))"
+ {:tag Boolean}
+ [x y] (not (= x y)))
+
+(defn compare
+ "Comparator. Returns 0 if x equals y, -1 if x is logically 'less
+ than' y, else 1. Same as Java x.compareTo(y) except it also works
+ for nil, and compares numbers in a type-independent manner. x must
+ implement Comparable"
+ {:tag Integer
+ :inline (fn [x y] `(. clojure.lang.Util compare ~x ~y))}
+ [x y] (. clojure.lang.Util (compare x y)))
+
+(defmacro and
+ "Evaluates exprs one at a time, from left to right. If a form
+ returns logical false (nil or false), and returns that value and
+ doesn't evaluate any of the other expressions, otherwise it returns
+ the value of the last expr. (and) returns true."
+ ([] true)
+ ([x] x)
+ ([x & rest]
+ `(let [and# ~x]
+ (if and# (and ~@rest) and#))))
+
+(defmacro or
+ "Evaluates exprs one at a time, from left to right. If a form
+ returns a logical true value, or returns that value and doesn't
+ evaluate any of the other expressions, otherwise it returns the
+ value of the last expression. (or) returns nil."
+ ([] nil)
+ ([x] x)
+ ([x & rest]
+ `(let [or# ~x]
+ (if or# or# (or ~@rest)))))
+
+;;;;;;;;;;;;;;;;;;; sequence fns ;;;;;;;;;;;;;;;;;;;;;;;
+(defn reduce
+ "f should be a function of 2 arguments. If val is not supplied,
+ returns the result of applying f to the first 2 items in coll, then
+ applying f to that result and the 3rd item, etc. If coll contains no
+ items, f must accept no arguments as well, and reduce returns the
+ result of calling f with no arguments. If coll has only 1 item, it
+ is returned and f is not called. If val is supplied, returns the
+ result of applying f to val and the first item in coll, then
+ applying f to that result and the 2nd item, etc. If coll contains no
+ items, returns val and f is not called."
+ ([f coll]
+ (let [s (seq coll)]
+ (if s
+ (if (instance? clojure.lang.IReduce s)
+ (. #^clojure.lang.IReduce s (reduce f))
+ (reduce f (first s) (rest s)))
+ (f))))
+ ([f val coll]
+ (let [s (seq coll)]
+ (if (instance? clojure.lang.IReduce s)
+ (. #^clojure.lang.IReduce s (reduce f val))
+ ((fn [f val s]
+ (if s
+ (recur f (f val (first s)) (rest s))
+ val)) f val s)))))
+
+(defn reverse
+ "Returns a seq of the items in coll in reverse order. Not lazy."
+ [coll]
+ (reduce conj nil coll))
+
+;;math stuff
+(defn +
+ "Returns the sum of nums. (+) returns 0."
+ {:inline (fn [x y] `(. clojure.lang.Numbers (add ~x ~y)))
+ :inline-arities #{2}}
+ ([] 0)
+ ([x] (cast Number x))
+ ([x y] (. clojure.lang.Numbers (add x y)))
+ ([x y & more]
+ (reduce + (+ x y) more)))
+
+(defn *
+ "Returns the product of nums. (*) returns 1."
+ {:inline (fn [x y] `(. clojure.lang.Numbers (multiply ~x ~y)))
+ :inline-arities #{2}}
+ ([] 1)
+ ([x] (cast Number x))
+ ([x y] (. clojure.lang.Numbers (multiply x y)))
+ ([x y & more]
+ (reduce * (* x y) more)))
+
+(defn /
+ "If no denominators are supplied, returns 1/numerator,
+ else returns numerator divided by all of the denominators."
+ {:inline (fn [x y] `(. clojure.lang.Numbers (divide ~x ~y)))
+ :inline-arities #{2}}
+ ([x] (/ 1 x))
+ ([x y] (. clojure.lang.Numbers (divide x y)))
+ ([x y & more]
+ (reduce / (/ x y) more)))
+
+(defn -
+ "If no ys are supplied, returns the negation of x, else subtracts
+ the ys from x and returns the result."
+ {:inline (fn [& args] `(. clojure.lang.Numbers (minus ~@args)))
+ :inline-arities #{1 2}}
+ ([x] (. clojure.lang.Numbers (minus x)))
+ ([x y] (. clojure.lang.Numbers (minus x y)))
+ ([x y & more]
+ (reduce - (- x y) more)))
+
+(defn <
+ "Returns non-nil if nums are in monotonically increasing order,
+ otherwise false."
+ {:inline (fn [x y] `(. clojure.lang.Numbers (lt ~x ~y)))
+ :inline-arities #{2}}
+ ([x] true)
+ ([x y] (. clojure.lang.Numbers (lt x y)))
+ ([x y & more]
+ (if (< x y)
+ (if (rest more)
+ (recur y (first more) (rest more))
+ (< y (first more)))
+ false)))
+
+(defn <=
+ "Returns non-nil if nums are in monotonically non-decreasing order,
+ otherwise false."
+ {:inline (fn [x y] `(. clojure.lang.Numbers (lte ~x ~y)))
+ :inline-arities #{2}}
+ ([x] true)
+ ([x y] (. clojure.lang.Numbers (lte x y)))
+ ([x y & more]
+ (if (<= x y)
+ (if (rest more)
+ (recur y (first more) (rest more))
+ (<= y (first more)))
+ false)))
+
+(defn >
+ "Returns non-nil if nums are in monotonically decreasing order,
+ otherwise false."
+ {:inline (fn [x y] `(. clojure.lang.Numbers (gt ~x ~y)))
+ :inline-arities #{2}}
+ ([x] true)
+ ([x y] (. clojure.lang.Numbers (gt x y)))
+ ([x y & more]
+ (if (> x y)
+ (if (rest more)
+ (recur y (first more) (rest more))
+ (> y (first more)))
+ false)))
+
+(defn >=
+ "Returns non-nil if nums are in monotonically non-increasing order,
+ otherwise false."
+ {:inline (fn [x y] `(. clojure.lang.Numbers (gte ~x ~y)))
+ :inline-arities #{2}}
+ ([x] true)
+ ([x y] (. clojure.lang.Numbers (gte x y)))
+ ([x y & more]
+ (if (>= x y)
+ (if (rest more)
+ (recur y (first more) (rest more))
+ (>= y (first more)))
+ false)))
+
+(defn ==
+ "Returns non-nil if nums all have the same value, otherwise false"
+ {:inline (fn [x y] `(. clojure.lang.Numbers (equiv ~x ~y)))
+ :inline-arities #{2}}
+ ([x] true)
+ ([x y] (. clojure.lang.Numbers (equiv x y)))
+ ([x y & more]
+ (if (== x y)
+ (if (rest more)
+ (recur y (first more) (rest more))
+ (== y (first more)))
+ false)))
+
+(defn max
+ "Returns the greatest of the nums."
+ ([x] x)
+ ([x y] (if (> x y) x y))
+ ([x y & more]
+ (reduce max (max x y) more)))
+
+(defn min
+ "Returns the least of the nums."
+ ([x] x)
+ ([x y] (if (< x y) x y))
+ ([x y & more]
+ (reduce min (min x y) more)))
+
+(defn inc
+ "Returns a number one greater than num."
+ {:inline (fn [x] `(. clojure.lang.Numbers (inc ~x)))}
+ [x] (. clojure.lang.Numbers (inc x)))
+
+(defn dec
+ "Returns a number one less than num."
+ {:inline (fn [x] `(. clojure.lang.Numbers (dec ~x)))}
+ [x] (. clojure.lang.Numbers (dec x)))
+
+(defn unchecked-inc
+ "Returns a number one greater than x, an int or long.
+ Note - uses a primitive operator subject to overflow."
+ {:inline (fn [x] `(. clojure.lang.Numbers (unchecked_inc ~x)))}
+ [x] (. clojure.lang.Numbers (unchecked_inc x)))
+
+(defn unchecked-dec
+ "Returns a number one less than x, an int or long.
+ Note - uses a primitive operator subject to overflow."
+ {:inline (fn [x] `(. clojure.lang.Numbers (unchecked_dec ~x)))}
+ [x] (. clojure.lang.Numbers (unchecked_dec x)))
+
+(defn unchecked-negate
+ "Returns the negation of x, an int or long.
+ Note - uses a primitive operator subject to overflow."
+ {:inline (fn [x] `(. clojure.lang.Numbers (unchecked_negate ~x)))}
+ [x] (. clojure.lang.Numbers (unchecked_negate x)))
+
+(defn unchecked-add
+ "Returns the sum of x and y, both int or long.
+ Note - uses a primitive operator subject to overflow."
+ {:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_add ~x ~y)))}
+ [x y] (. clojure.lang.Numbers (unchecked_add x y)))
+
+(defn unchecked-subtract
+ "Returns the difference of x and y, both int or long.
+ Note - uses a primitive operator subject to overflow."
+ {:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_subtract ~x ~y)))}
+ [x y] (. clojure.lang.Numbers (unchecked_subtract x y)))
+
+(defn unchecked-multiply
+ "Returns the product of x and y, both int or long.
+ Note - uses a primitive operator subject to overflow."
+ {:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_multiply ~x ~y)))}
+ [x y] (. clojure.lang.Numbers (unchecked_multiply x y)))
+
+(defn unchecked-divide
+ "Returns the division of x by y, both int or long.
+ Note - uses a primitive operator subject to truncation."
+ {:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_divide ~x ~y)))}
+ [x y] (. clojure.lang.Numbers (unchecked_divide x y)))
+
+(defn pos?
+ "Returns true if num is greater than zero, else false"
+ {:tag Boolean
+ :inline (fn [x] `(. clojure.lang.Numbers (isPos ~x)))}
+ [x] (. clojure.lang.Numbers (isPos x)))
+
+(defn neg?
+ "Returns true if num is less than zero, else false"
+ {:tag Boolean
+ :inline (fn [x] `(. clojure.lang.Numbers (isNeg ~x)))}
+ [x] (. clojure.lang.Numbers (isNeg x)))
+
+(defn zero?
+ "Returns true if num is zero, else false"
+ {:tag Boolean
+ :inline (fn [x] `(. clojure.lang.Numbers (isZero ~x)))}
+ [x] (. clojure.lang.Numbers (isZero x)))
+
+(defn quot
+ "quot[ient] of dividing numerator by denominator."
+ [num div]
+ (. clojure.lang.Numbers (quotient num div)))
+
+(defn rem
+ "rem[ainder] of dividing numerator by denominator."
+ [num div]
+ (. clojure.lang.Numbers (remainder num div)))
+
+(defn rationalize
+ "returns the rational value of num"
+ [num]
+ (. clojure.lang.Numbers (rationalize num)))
+
+;;Bit ops
+
+(defn bit-not
+ "Bitwise complement"
+ [x] (. clojure.lang.Numbers not x))
+
+
+(defn bit-and
+ "Bitwise and"
+ [x y] (. clojure.lang.Numbers and x y))
+
+(defn bit-or
+ "Bitwise or"
+ [x y] (. clojure.lang.Numbers or x y))
+
+(defn bit-xor
+ "Bitwise exclusive or"
+ [x y] (. clojure.lang.Numbers xor x y))
+
+(defn bit-and-not
+ "Bitwise and with complement"
+ [x y] (. clojure.lang.Numbers andNot x y))
+
+
+(defn bit-clear
+ "Clear bit at index n"
+ [x n] (. clojure.lang.Numbers clearBit x n))
+
+(defn bit-set
+ "Set bit at index n"
+ [x n] (. clojure.lang.Numbers setBit x n))
+
+(defn bit-flip
+ "Flip bit at index n"
+ [x n] (. clojure.lang.Numbers flipBit x n))
+
+(defn bit-test
+ "Test bit at index n"
+ [x n] (. clojure.lang.Numbers testBit x n))
+
+
+(defn bit-shift-left
+ "Bitwise shift left"
+ [x n] (. clojure.lang.Numbers shiftLeft x n))
+
+(defn bit-shift-right
+ "Bitwise shift right"
+ [x n] (. clojure.lang.Numbers shiftRight x n))
+
+;;
+
+(defn complement
+ "Takes a fn f and returns a fn that takes the same arguments as f,
+ has the same effects, if any, and returns the opposite truth value."
+ [f] (fn [& args]
+ (not (apply f args))))
+
+(defn constantly
+ "Returns a function that takes any number of arguments and returns x."
+ [x] (fn [& args] x))
+
+(defn identity
+ "Returns its argument."
+ [x] x)
+
+;;Collection stuff
+
+
+
+(defn count
+ "Returns the number of items in the collection. (count nil) returns
+ 0. Also works on strings, arrays, and Java Collections and Maps"
+ [coll] (. clojure.lang.RT (count coll)))
+
+;;list stuff
+(defn peek
+ "For a list or queue, same as first, for a vector, same as, but much
+ more efficient than, last. If the collection is empty, returns nil."
+ [coll] (. clojure.lang.RT (peek coll)))
+
+(defn pop
+ "For a list or queue, returns a new list/queue without the first
+ item, for a vector, returns a new vector without the last item. If
+ the collection is empty, throws an exception. Note - not the same
+ as rest/butlast."
+ [coll] (. clojure.lang.RT (pop coll)))
+
+(defn nth
+ "Returns the value at the index. get returns nil if index out of
+ bounds, nth throws an exception unless not-found is supplied. nth
+ also works for strings, Java arrays, regex Matchers and Lists, and,
+ in O(n) time, for sequences."
+ ([coll index] (. clojure.lang.RT (nth coll index)))
+ ([coll index not-found] (. clojure.lang.RT (nth coll index not-found))))
+
+;;map stuff
+
+(defn contains?
+ "Returns true if key is present, else false."
+ [map key] (. clojure.lang.RT (contains map key)))
+
+(defn get
+ "Returns the value mapped to key, not-found or nil if key not present."
+ ([map key]
+ (. clojure.lang.RT (get map key)))
+ ([map key not-found]
+ (. clojure.lang.RT (get map key not-found))))
+
+(defn dissoc
+ "dissoc[iate]. Returns a new map of the same (hashed/sorted) type,
+ that does not contain a mapping for key(s)."
+ ([map] map)
+ ([map key]
+ (. clojure.lang.RT (dissoc map key)))
+ ([map key & ks]
+ (let [ret (dissoc map key)]
+ (if ks
+ (recur ret (first ks) (rest ks))
+ ret))))
+
+(defn disj
+ "disj[oin]. Returns a new set of the same (hashed/sorted) type, that
+ does not contain key(s)."
+ ([set] set)
+ ([#^clojure.lang.IPersistentSet set key]
+ (. set (disjoin key)))
+ ([set key & ks]
+ (let [ret (disj set key)]
+ (if ks
+ (recur ret (first ks) (rest ks))
+ ret))))
+
+(defn find
+ "Returns the map entry for key, or nil if key not present."
+ [map key] (. clojure.lang.RT (find map key)))
+
+(defn select-keys
+ "Returns a map containing only those entries in map whose key is in keys"
+ [map keyseq]
+ (loop [ret {} keys (seq keyseq)]
+ (if keys
+ (let [entry (. clojure.lang.RT (find map (first keys)))]
+ (recur
+ (if entry
+ (conj ret entry)
+ ret)
+ (rest keys)))
+ ret)))
+
+(defn keys
+ "Returns a sequence of the map's keys."
+ [map] (. clojure.lang.RT (keys map)))
+
+(defn vals
+ "Returns a sequence of the map's values."
+ [map] (. clojure.lang.RT (vals map)))
+
+(defn key
+ "Returns the key of the map entry."
+ [#^java.util.Map$Entry e]
+ (. e (getKey)))
+
+(defn val
+ "Returns the value in the map entry."
+ [#^java.util.Map$Entry e]
+ (. e (getValue)))
+
+(defn rseq
+ "Returns, in constant time, a sequence of the items in rev (which
+ can be a vector or sorted-map), in reverse order."
+ [#^clojure.lang.Reversible rev]
+ (. rev (rseq)))
+
+(defn name
+ "Returns the name String of a symbol or keyword."
+ [#^clojure.lang.Named x]
+ (. x (getName)))
+
+(defn namespace
+ "Returns the namespace String of a symbol or keyword, or nil if not present."
+ [#^clojure.lang.Named x]
+ (. x (getNamespace)))
+
+(defmacro locking
+ "Executes exprs in an implicit do, while holding the monitor of x.
+ Will release the monitor of x in all circumstances."
+ [x & body]
+ `(let [lockee# ~x]
+ (try
+ (monitor-enter lockee#)
+ ~@body
+ (finally
+ (monitor-exit lockee#)))))
+
+(defmacro ..
+ "form => fieldName-symbol or (instanceMethodName-symbol args*)
+
+ Expands into a member access (.) of the first member on the first
+ argument, followed by the next member on the result, etc. For
+ instance:
+
+ (.. System (getProperties) (get \"os.name\"))
+
+ expands to:
+
+ (. (. System (getProperties)) (get \"os.name\"))
+
+ but is easier to write, read, and understand."
+ ([x form] `(. ~x ~form))
+ ([x form & more] `(.. (. ~x ~form) ~@more)))
+
+(defmacro ->
+ "Macro. Threads the expr through the forms. Inserts x as the
+ second item in the first form, making a list of it if it is not a
+ list already. If there are more forms, inserts the first form as the
+ second item in second form, etc."
+ ([x form] (if (seq? form)
+ `(~(first form) ~x ~@(rest form))
+ (list form x)))
+ ([x form & more] `(-> (-> ~x ~form) ~@more)))
+
+;;multimethods
+(defmacro defmulti
+ "Creates a new multimethod with the associated dispatch function. If
+ default-dispatch-val is supplied it becomes the default dispatch
+ value of the multimethod, otherwise the default dispatch value
+ is :default."
+ ([name dispatch-fn] `(defmulti ~name ~dispatch-fn :default))
+ ([name dispatch-fn default-val]
+ `(def ~name (new clojure.lang.MultiFn ~dispatch-fn ~default-val))))
+
+(defmacro defmethod
+ "Creates and installs a new method of multimethod associated with dispatch-value. "
+ [multifn dispatch-val & fn-tail]
+ `(. ~multifn addMethod ~dispatch-val (fn ~@fn-tail)))
+
+(defmacro remove-method
+ "Removes the method of multimethod associated with dispatch-value."
+ [multifn dispatch-val]
+ `(. ~multifn removeMethod ~dispatch-val))
+
+(defmacro prefer-method
+ "Causes the multimethod to prefer matches of dispatch-val-x over dispatch-val-y when there is a conflict"
+ [multifn dispatch-val-x dispatch-val-y]
+ `(. ~multifn preferMethod ~dispatch-val-x ~dispatch-val-y))
+
+;;;;;;;;; var stuff
+
+(defmacro binding
+ "binding => var-symbol init-expr
+
+ Creates new bindings for the (already-existing) vars, with the
+ supplied initial values, executes the exprs in an implicit do, then
+ re-establishes the bindings that existed before."
+ [bindings & body]
+ (let [var-ize (fn [var-vals]
+ (loop [ret [] vvs (seq var-vals)]
+ (if vvs
+ (recur (conj (conj ret `(var ~(first vvs))) (second vvs))
+ (rest (rest vvs)))
+ (seq ret))))]
+ `(do
+ (. clojure.lang.Var (pushThreadBindings (hash-map ~@(var-ize bindings))))
+ (try
+ ~@body
+ (finally
+ (. clojure.lang.Var (popThreadBindings)))))))
+
+(defn find-var
+ "Returns the global var named by the namespace-qualified symbol, or
+ nil if no var with that name."
+ [sym] (. clojure.lang.Var (find sym)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Refs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defn agent
+ "Creates and returns an agent with an initial value of state and an
+ optional validate fn. validate-fn must be nil or a side-effect-free fn of
+ one argument, which will be passed the intended new state on any state
+ change. If the new state is unacceptable, the validate-fn should
+ throw an exception."
+ ([state] (new clojure.lang.Agent state))
+ ([state validate-fn] (new clojure.lang.Agent state validate-fn)))
+
+(defn ! [& args] (throw (new Exception "! is now send. See also send-off")))
+
+(defn send
+ "Dispatch an action to an agent. Returns the agent immediately.
+ Subsequently, in a thread from a thread pool, the state of the agent
+ will be set to the value of:
+
+ (apply action-fn state-of-agent args)"
+ [#^clojure.lang.Agent a f & args]
+ (. a (dispatch f args false)))
+
+(defn send-off
+ "Dispatch a potentially blocking action to an agent. Returns the
+ agent immediately. Subsequently, in a separate thread, the state of
+ the agent will be set to the value of:
+
+ (apply action-fn state-of-agent args)"
+ [#^clojure.lang.Agent a f & args]
+ (. a (dispatch f args true)))
+
+(defn agent-errors
+ "Returns a sequence of the exceptions thrown during asynchronous
+ actions of the agent."
+ [#^clojure.lang.Agent a] (. a (getErrors)))
+
+(defn clear-agent-errors
+ "Clears any exceptions thrown during asynchronous actions of the
+ agent, allowing subsequent actions to occur."
+ [#^clojure.lang.Agent a] (. a (clearErrors)))
+
+(defn shutdown-agents
+ "Initiates a shutdown of the thread pools that back the agent
+ system. Running actions will complete, but no new actions will be
+ accepted"
+ [] (. clojure.lang.Agent shutdown))
+
+(defn ref
+ "Creates and returns a Ref with an initial value of x and an optional validate fn.
+ validate-fn must be nil or a side-effect-free fn of one argument, which will
+ be passed the intended new state on any state change. If the new
+ state is unacceptable, the validate-fn should throw an
+ exception. validate-fn will be called on transaction commit, when
+ all refs have their final values."
+ ([x] (new clojure.lang.Ref x))
+ ([x validate-fn] (new clojure.lang.Ref x validate-fn)))
+
+(defn deref