diff options
-rw-r--r-- | src/clj/clojure/boot.clj | 2863 | ||||
-rw-r--r-- | src/clj/clojure/genclass.clj | 520 | ||||
-rw-r--r-- | src/clj/clojure/inspector/inspector.clj | 110 | ||||
-rw-r--r-- | src/clj/clojure/parallel/parallel.clj | 249 | ||||
-rw-r--r-- | src/clj/clojure/proxy.clj | 307 | ||||
-rw-r--r-- | src/clj/clojure/set/set.clj | 116 | ||||
-rw-r--r-- | src/clj/clojure/xml/xml.clj | 117 | ||||
-rw-r--r-- | src/clj/clojure/zip/zip.clj | 248 |
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 + "Also reader macro: @ref/@agent Within a transaction, returns the + in-transaction-value of ref, else returns the + most-recently-committed value of ref. When applied to an agent, + returns its current state." + [#^clojure.lang.IRef ref] (. ref (get))) + +(defn set-validator + "Sets the validator-fn for a var/ref/agent. validator-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 + validator-fn should throw an exception. If the current state (root + value if var) is not acceptable to the new validator, an exception + will be thrown and the validator will not be changed." + [#^clojure.lang.IRef iref validator-fn] (. iref (setValidator validator-fn))) + +(defn get-validator + "Gets the validator-fn for a var/ref/agent." + [#^clojure.lang.IRef iref] (. iref (getValidator))) + +(defn commute + "Must be called in a transaction. Sets the in-transaction-value of |