diff options
author | Rich Hickey <richhickey@gmail.com> | 2008-07-21 21:17:06 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2008-07-21 21:17:06 +0000 |
commit | 2d7bb725966b98ff32f410fb1162286ae87961c6 (patch) | |
tree | 8935e5c9961b855c721012c87ea38c71700c3ce3 | |
parent | 4c38b36cfb0fef594f06484cfaf99fb6a0b676de (diff) |
removed root-level .cljs
-rw-r--r-- | src/boot.clj | 2670 | ||||
-rw-r--r-- | src/genclass.clj | 517 | ||||
-rw-r--r-- | src/inspector.clj | 110 | ||||
-rw-r--r-- | src/parallel.clj | 248 | ||||
-rw-r--r-- | src/proxy.clj | 307 | ||||
-rw-r--r-- | src/set.clj | 116 | ||||
-rw-r--r-- | src/xml.clj | 117 | ||||
-rw-r--r-- | src/zip.clj | 248 |
8 files changed, 0 insertions, 4333 deletions
diff --git a/src/boot.clj b/src/boot.clj deleted file mode 100644 index 89cda99d..00000000 --- a/src/boot.clj +++ /dev/null @@ -1,2670 +0,0 @@ -; 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] - `(let [pvar# (var ~multifn)] - (. pvar# (commuteRoot (fn [#^clojure.lang.MultiFn mf#] - (. mf# (assoc ~dispatch-val (fn ~@fn-tail)))))))) - -(defmacro remove-method - "Removes the method of multimethod associated with dispatch-value." - [multifn dispatch-val] - `(let [pvar# (var ~multifn)] - (. pvar# (commuteRoot (fn [#^clojure.lang.MultiFn mf#] - (. mf# (dissoc ~dispatch-val))))))) - -;;;;;;;;; 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." - [state] (new clojure.lang.Agent state)) - -(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 ref - "Creates and returns a Ref with an initial value of x." - [x] (new clojure.lang.Ref x)) - -(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 commute - "Must be called in a transaction. Sets the in-transaction-value of - ref to: - - (apply fun in-transaction-value-of-ref args) - - and returns the in-transaction-value of ref. - - At the commit point of the transaction, sets the value of ref to be: - - (apply fun most-recently-committed-value-of-ref args) - - Thus fun should be commutative, or, failing that, you must accept - last-one-in-wins behavior. commute allows for more concurrency than - ref-set." - - [#^clojure.lang.Ref ref fun & args] - (. ref (commute fun args))) - -(defn alter - "Must be called in a transaction. Sets the in-transaction-value of - ref to: - - (apply fun in-transaction-value-of-ref args) - - and returns the in-transaction-value of ref." - [#^clojure.lang.Ref ref fun & args] - (. ref (alter fun args))) - -(defn ref-set - "Must be called in a transaction. Sets the value of ref. - Returns val." - [#^clojure.lang.Ref ref val] - (. ref (set val))) - -(defn ensure - "Must be called in a transaction. Protects the ref from modification - by other transactions. Returns the in-transaction-value of - ref. Allows for more concurrency than (ref-set ref @ref)" - [#^clojure.lang.Ref ref] - (. ref (touch)) - (. ref (get))) - -(defmacro sync - "transaction-flags => TBD, pass nil for now - - Runs the exprs (in an implicit do) in a transaction that encompasses - exprs and any nested calls. Starts a transaction if none is already - running on this thread. Any uncaught exception will abort the - transaction and flow out of sync. The exprs may be run more than - once, but any effects on Refs will be atomic." - [flags-ignored-for-now & body] - `(. clojure.lang.LockingTransaction - (runInTransaction (fn [] ~@body)))) - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fn stuff ;;;;;;;;;;;;;;;; - - -(defn comp - "Takes a set of functions and returns a fn that is the composition - of those fns. The returned fn takes a variable number of args, - applies the rightmost of fns to the args, the next - fn (right-to-left) to the result, etc." - [& fs] - (let [fs (reverse fs)] - (fn [& args] - (loop [ret (apply (first fs) args) fs (rest fs)] - (if fs - (recur ((first fs) ret) (rest fs)) - ret))))) - -(defn partial - "Takes a function f and fewer than the normal arguments to f, and - returns a fn that takes a variable number of additional args. When - called, the returned function calls f with args + additional args." - ([f arg1] - (fn [& args] (apply f arg1 args))) - ([f arg1 arg2] - (fn [& args] (apply f arg1 arg2 args))) - ([f arg1 arg2 arg3] - (fn [& args] (apply f arg1 arg2 arg3 args))) - ([f arg1 arg2 arg3 & more] - (fn [& args] (apply f arg1 arg2 arg3 (concat more args))))) - -;;;;;;;;;;;;;;;;;;; sequence fns ;;;;;;;;;;;;;;;;;;;;;;; - -(defn every? - "Returns true if (pred x) is logical true for every x in coll, else - false." - {:tag Boolean} - [pred coll] - (if (seq coll) - (and (pred (first coll)) - (recur pred (rest coll))) - true)) - -(def - #^{:tag Boolean - :doc "Returns false if (pred x) is logical true for every x in - coll, else true." - :arglists '([pred coll])} -not-every? (comp not every?)) - -(defn some - "Returns the first logical true value of (pred x) for any x in coll, - else nil." - [pred coll] - (when (seq coll) - (or (pred (first coll)) (recur pred (rest coll))))) - -(def - #^{:tag Boolean - :doc "Returns false if (pred x) is logical true for any x in coll, - else true." - :arglists '([pred coll])} - not-any? (comp not some)) - -(defn map - "Returns a lazy seq consisting of the result of applying f to the - set of first items of each coll, followed by applying f to the set - of second items in each coll, until any one of the colls is - exhausted. Any remaining items in other colls are ignored. Function - f should accept number-of-colls arguments." - ([f coll] - (when (seq coll) - (lazy-cons (f (first coll)) (map f (rest coll))))) - ([f coll & colls] - (when (and (seq coll) (every? seq colls)) - (lazy-cons (apply f (first coll) (map first colls)) - (apply map f (rest coll) (map rest colls)))))) - -(defn mapcat - "Returns the result of applying concat to the result of applying map - to f and colls. Thus function f should return a collection." - [f & colls] - (apply concat (apply map f colls))) - -(defn filter - "Returns a lazy seq of the items in coll for which - (pred item) returns true." - [pred coll] - (when (seq coll) - (if (pred (first coll)) - (lazy-cons (first coll) (filter pred (rest coll))) - (recur pred (rest coll))))) - -(defn take - "Returns a lazy seq of the first n items in coll, or all items if - there are fewer than n." - [n coll] - (when (and (pos? n) (seq coll)) - (lazy-cons (first coll) (take (dec n) (rest coll))))) - -(defn take-while - "Returns a lazy seq of successive items from coll while - (pred item) returns true." - [pred coll] - (when (and (seq coll) (pred (first coll))) - (lazy-cons (first coll) (take-while pred (rest coll))))) - -(defn drop - "Returns a lazy seq of all but the first n items in coll." - [n coll] - (if (and (pos? n) (seq coll)) - (recur (dec n) (rest coll)) - (seq coll))) - -(defn drop-last - "Return a lazy seq of all but the last n (default 1) items in coll" - ([s] (drop-last 1 s)) - ([n s] (map (fn [x _] x) (seq s) (drop n s)))) - -(defn drop-while - "Returns a lazy seq of the items in coll starting from the first - item for which (pred item) returns nil." - [pred coll] - (if (and (seq coll) (pred (first coll))) - (recur pred (rest coll)) - (seq coll))) - -(defn cycle - "Returns a lazy (infinite!) seq of repetitions of the items in - coll." - [coll] - (when (seq coll) - (let [rep (fn thisfn [xs] - (if xs - (lazy-cons (first xs) (thisfn (rest xs))) - (recur (seq coll))))] - (rep (seq coll))))) - -(defn split-at - "Returns a vector of [(take n coll) (drop n coll)]" - [n coll] - [(take n coll) (drop n coll)]) - -(defn split-with - "Returns a vector of [(take-while pred coll) (drop-while pred coll)]" - [pred coll] - [(take-while pred coll) (drop-while pred coll)]) - -(defn repeat - "Returns a lazy (infinite!) seq of xs." - [x] (lazy-cons x (repeat x))) - -(defn replicate - "Returns a lazy seq of n xs." - [n x] (take n (repeat x))) - -(defn iterate - "Returns a lazy seq of x, (f x), (f (f x)) etc." - [f x] (lazy-cons x (iterate f (f x)))) - -(defn range - "Returns a lazy seq of nums from start (inclusive) to end - (exclusive), by step, where start defaults to 0 and step to 1." - ([end] (if (and (> end 0) (< end (. Integer MAX_VALUE))) - (new clojure.lang.Range 0 end) - (take end (iterate inc 0)))) - ([start end] (if (and (< start end) (< end (. Integer MAX_VALUE))) - (new clojure.lang.Range start end) - (take (- end start) (iterate inc start)))) - ([start end step] - (take-while (partial (if (pos? step) > <) end) (iterate (partial + step) start)))) - -(defn merge - "Returns a map that consists of the rest of the maps conj-ed onto - the first. If a key occurs in more than one map, the mapping from - the latter (left-to-right) will be the mapping in the result." - [& maps] (reduce conj maps)) - -(defn merge-with - "Returns a map that consists of the rest of the maps conj-ed onto - the first. If a key occurs in more than one map, the mapping(s) - from the latter (left-to-right) will be combined with the mapping in - the result by calling (f val-in-result val-in-latter)." - [f & maps] - (let [merge-entry (fn [m e] - (let [k (key e) v (val e)] - (if (contains? m k) - (assoc m k (f (m k) v)) - (assoc m k v)))) - merge2 (fn [m1 m2] - (reduce merge-entry m1 (seq m2)))] - (reduce merge2 maps))) - - - -(defn zipmap - "Returns a map with the keys mapped to the corresponding vals." - [keys vals] - (loop [map {} - ks (seq keys) - vs (seq vals)] - (if (and ks vs) - (recur (assoc map (first ks) (first vs)) - (rest ks) - (rest vs)) - map))) - -(defn line-seq - "Returns the lines of text from rdr as a lazy sequence of strings. - rdr must implement java.io.BufferedReader." - [#^java.io.BufferedReader rdr] - (let [line (. rdr (readLine))] - (when line - (lazy-cons line (line-seq rdr))))) - -(defn comparator - "Returns an implementation of java.util.Comparator based upon pred." - [pred] - (fn [x y] - (cond (pred x y) -1 (pred y x) 1 :else 0))) - -(defn sort - "Returns a sorted sequence of the items in coll. If no comparator is - supplied, uses compare. comparator must - implement java.util.Comparator." - ([#^java.util.Collection coll] - (sort compare coll)) - ([#^java.util.Comparator comp #^java.util.Collection coll] - (when (and coll (not (. coll (isEmpty)))) - (let [a (. coll (toArray))] - (. java.util.Arrays (sort a comp)) - (seq a))))) - -(defn sort-by - "Returns a sorted sequence of the items in coll, where the sort - order is determined by comparing (keyfn item). If no comparator is - supplied, uses compare. comparator must - implement java.util.Comparator." - ([keyfn coll] - (sort-by keyfn compare coll)) - ([keyfn #^java.util.Comparator comp coll] - (sort (fn [x y] (. comp (compare (keyfn x) (keyfn y)))) coll))) - -;; evaluation - -(defn eval - "Evaluates the form data structure (not text!) and returns the result." - [form] (. clojure.lang.Compiler (eval form))) - -;(defn defimports [& imports-maps] -; (def *imports* (apply merge imports-maps))) - -(defmacro doseq - "Repeatedly executes body (presumably for side-effects) with - binding-form bound to successive items from coll. Does not retain - the head of the sequence. Returns nil." - [item list & body] - `(loop [list# (seq ~list)] - (when list# - (let [~item (first list#)] - ~@body) - (recur (rest list#))))) - -(defn scan [& args] (throw (new Exception "scan is now called dorun"))) -(defn touch [& args] (throw (new Exception "touch is now called doall"))) - -(defn dorun - "When lazy sequences are produced via functions that have side - effects, any effects other than those needed to produce the first - element in the seq do not occur until the seq is consumed. dorun can - be used to force any effects. Walks through the successive rests of - the seq, does not retain the head and returns nil." - ([coll] - (when (seq coll) - (recur (rest coll)))) - ([n coll] - (when (and (seq coll) (pos? n)) - (recur (dec n) (rest coll))))) - -(defn doall - "When lazy sequences are produced via functions that have side - effects, any effects other than those needed to produce the first - element in the seq do not occur until the seq is consumed. doall can - be used to force any effects. Walks through the successive rests of - the seq, retains the head and returns it, thus causing the entire - seq to reside in memory at one time." - ([coll] - (dorun coll) - coll) - ([n coll] - (dorun n coll) - coll)) - -(defn await - "Blocks the current thread (indefinitely!) until all actions - dispatched thus far, from this thread or agent, to the agent(s) have - occurred." - [& agents] - (when *agent* - (throw (new Exception "Can't await in agent action"))) - (let [latch (new java.util.concurrent.CountDownLatch (count agents)) - count-down (fn [agent] (. latch (countDown)) agent)] - (doseq agent agents - (send agent count-down)) - (. latch (await)))) - -(defn await1 [#^clojure.lang.Agent a] - (when (pos? (.getQueueCount a)) - (await a)) - a) - -(defn await-for - "Blocks the current thread until all actions dispatched thus - far (from this thread or agent) to the agents have occurred, or the - timeout (in milliseconds) has elapsed. Returns nil if returning due - to timeout, non-nil otherwise." - [timeout-ms & agents] - (when *agent* - (throw (new Exception "Can't await in agent action"))) - (let [latch (new java.util.concurrent.CountDownLatch (count agents)) - count-down (fn [agent] (. latch (countDown)) agent)] - (doseq agent agents - (send agent count-down)) - (. latch (await timeout-ms (. java.util.concurrent.TimeUnit MILLISECONDS))))) - -(defmacro dotimes - "Repeatedly executes body (presumably for side-effects) with name - bound to integers from 0 through n-1." - [i n & body] - `(let [n# (int ~n)] - (loop [~i (int 0)] - (when (< ~i n#) - ~@body - (recur (unchecked-inc ~i)))))) - -(defn import - "import-list => (package-symbol class-name-symbols*) - - For each name in class-name-symbols, adds a mapping from name to the - class named by package.name to the current namespace." - [& import-lists] - (when import-lists - (let [#^clojure.lang.Namespace ns *ns* - pkg (ffirst import-lists) - classes (rfirst import-lists)] - (doseq c classes - (. ns (importClass c (. Class (forName (str pkg "." c)))))) ) - (apply import (rest import-lists)))) - -(defn into-array - "Returns an array of the type of the first element in coll, - containing the contents of coll, which must be of a compatible - type." - [aseq] - (. clojure.lang.RT (seqToTypedArray (seq aseq)))) - -(defn into - "Returns a new coll consisting of to-coll with all of the items of - from-coll conjoined." - [to from] - (let [ret to items (seq from)] - (if items - (recur (conj ret (first items)) (rest items)) - ret))) - -(defn #^{:private true} - array [& items] - (into-array items)) - -(defn pr - "Prints the object(s) to the output stream that is the current value - of *out*. Prints the object(s), separated by spaces if there is - more than one. By default, pr and prn print in a way that objects - can be read by the reader" - ([] nil) - ([x] - (. clojure.lang.RT (print x *out*)) - nil) - ([x & more] - (pr x) - (. *out* (append \space)) - (apply pr more))) - -(defn newline - "Writes a newline to the output stream that is the current value of - *out*" - [] - (. *out* (append \newline)) - nil) - -(defn flush - "Flushes the output stream that is the current value of - *out*" - [] - (. *out* (flush)) - nil) - -(defn prn - "Same as pr followed by (newline). Observes *flush-on-newline*" - [& more] - (apply pr more) - (newline) - (when *flush-on-newline* - (flush))) - -(defn print - "Prints the object(s) to the output stream that is the current value - of *out*. print and println produce output for human consumption." - [& more] - (binding [*print-readably* nil] - (apply pr more))) - -(defn println - "Same as print followed by (newline)" - [& more] - (binding [*print-readably* nil] - (apply prn more))) - - -(defn read - "Reads the next object from stream, which must be an instance of - java.io.PushbackReader or some derivee. stream defaults to the - current value of *in* ." - ([] - (read *in*)) - ([stream] - (read stream true nil)) - ([stream eof-error? eof-value] - (read stream eof-error? eof-value false)) - ([stream eof-error? eof-value recursive?] - (. clojure.lang.LispReader (read stream eof-error? eof-value recursive?)))) - -(defn read-line - "Reads the next line from stream that is the current value of *in* ." - [] (. *in* (readLine))) - -(defmacro with-open - "Evaluates body in a try expression with name bound to the value of - init, and a finally clause that calls (. name (close))." - [name init & body] - `(let [~name ~init] - (try - ~@body - (finally - (. ~name (close)))))) - -(defmacro doto - "Evaluates x then calls all of the methods with the supplied - arguments in succession on the resulting object, returning it. - - (doto (new java.util.HashMap) (put \"a\" 1) (put \"b\" 2))" - [x & members] - (let [gx (gensym)] - `(let [~gx ~x] - (do - ~@(map (fn [m] (list '. gx m)) - members)) - ~gx))) - -(defmacro memfn - "Expands into code that creates a fn that expects to be passed an - object and any args and calls the named instance method on the - object passing the args. Use when you want to treat a Java method as - a first-class fn." - [name & args] - `(fn [target# ~@args] - (. target# (~name ~@args)))) - -(defmacro time - "Evaluates expr and prints the time it took. Returns the value of - expr." - [expr] - `(let [start# (. System (nanoTime)) - ret# ~expr] - (prn (str "Elapsed time: " (/ (double (- (. System (nanoTime)) start#)) 1000000.0) " msecs")) - ret#)) - -(defn num - "Coerce to Number" - {:tag Number - :inline (fn [x] `(. clojure.lang.Numbers (num ~x)))} - [x] (. clojure.lang.Numbers (num x))) - -(defn int - "Coerce to int" - {:tag Integer - :inline (fn [x] `(. clojure.lang.RT (intCast ~x)))} - [x] (. clojure.lang.RT (intCast x))) - -(defn long - "Coerce to long" - {:tag Long - :inline (fn [x] `(. clojure.lang.RT (longCast ~x)))} - [#^Number x] (. x (longValue))) - -(defn float - "Coerce to float" - {:tag Float - :inline (fn [x] `(. clojure.lang.RT (floatCast ~x)))} - [#^Number x] (. x (floatValue))) - -(defn double - "Coerce to double" - {:tag Double - :inline (fn [x] `(. clojure.lang.RT (doubleCast ~x)))} - [#^Number x] (. x (doubleValue))) - -(defn short - "Coerce to short" - {:tag Short} - [#^Number x] (. x (shortValue))) - -(defn byte - "Coerce to byte" - {:tag Byte} - [#^Number x] (. x (byteValue))) - -(defn char - "Coerce to char" - {:tag Character} - [x] (. clojure.lang.RT (charCast x))) - -(defn boolean - "Coerce to boolean" - {:tag Boolean} - [x] (if x true false)) - -(defn bigint - "Coerce to BigInteger" - {:tag BigInteger} - [x] (. BigInteger valueOf x)) - -(defn bigdec - "Coerce to BigDecimal" - {:tag BigDecimal} - [x] (. BigDecimal valueOf x)) - -(import '(java.lang.reflect Array)) - -(defn alength - "Returns the length of the Java array. Works on arrays of all - types." - {:inline (fn [a] `(. clojure.lang.RT (alength ~a)))} - [array] (. clojure.lang.RT (alength array))) - -(defn aclone - "Returns a clone of the Java array. Works on arrays of known - types." - {:inline (fn [a] `(. clojure.lang.RT (aclone ~a)))} - [array] (. clojure.lang.RT (aclone array))) - -(defn aget - "Returns the value at the index/indices. Works on Java arrays of all - types." - {:inline (fn [a i] `(. clojure.lang.RT (aget ~a ~i))) - :inline-arities #{2}} - ([array idx] - (. Array (get array idx))) - ([array idx & idxs] - (apply aget (aget array idx) idxs))) - -(defn aset - "Sets the value at the index/indices. Works on Java arrays of - reference types. Returns val." - {:inline (fn [a i v] `(. clojure.lang.RT (aset ~a ~i ~v))) - :inline-arities #{3}} - ([array idx val] - (. Array (set array idx val)) - val) - ([array idx idx2 & idxv] - (apply aset (aget array idx) idx2 idxv))) - -(defmacro - #^{:private true} - def-aset [name method coerce] - `(defn ~name - {:arglists '([~'array ~'idx ~'val] [~'array ~'idx ~'idx2 & ~'idxv])} - ([array# idx# val#] - (. Array (~method array# idx# (~coerce val#))) - val#) - ([array# idx# idx2# & idxv#] - (apply ~name (aget array# idx#) idx2# idxv#)))) - -(def-aset - #^{:doc "Sets the value at the index/indices. Works on arrays of int. Returns val."} - aset-int setInt int) - -(def-aset - #^{:doc "Sets the value at the index/indices. Works on arrays of long. Returns val."} - aset-long setLong long) - -(def-aset - #^{:doc "Sets the value at the index/indices. Works on arrays of boolean. Returns val."} - aset-boolean setBoolean boolean) - -(def-aset - #^{:doc "Sets the value at the index/indices. Works on arrays of float. Returns val."} - aset-float setFloat float) - -(def-aset - #^{:doc "Sets the value at the index/indices. Works on arrays of double. Returns val."} - aset-double setDouble double) - -(def-aset - #^{:doc "Sets the value at the index/indices. Works on arrays of short. Returns val."} - aset-short setShort short) - -(def-aset - #^{:doc "Sets the value at the index/indices. Works on arrays of byte. Returns val."} - aset-byte setByte byte) - -(def-aset - #^{:doc "Sets the value at the index/indices. Works on arrays of char. Returns val."} - aset-char setChar char) - -(defn make-array - "Creates and returns an array of instances of the specified class of - the specified dimension(s). Note that a class object is required. - Class objects can be obtained by using their imported or - fully-qualified name. Class objects for the primitive types can be - obtained using, e.g., (. Integer TYPE)." - ([#^Class type len] - (. Array (newInstance type (int len)))) - ([#^Class type dim & more-dims] - (let [dims (cons dim more-dims) - #^"[I" dimarray (make-array (. Integer TYPE) (count dims))] - (dotimes i (alength dimarray) - (aset-int dimarray i (nth dims i))) - (. Array (newInstance type dimarray))))) - -(defn to-array-2d - "Returns a (potentially-ragged) 2-dimensional array of Objects - containing the contents of coll, which can be any Collection of any - Collection." - [#^java.util.Collection coll] - (let [ret (make-array (. Class (forName "[Ljava.lang.Object;")) (. coll (size)))] - (loop [i 0 xs (seq coll)] - (when xs - (aset ret i (to-array (first xs))) - (recur (inc i) (rest xs)))) - ret)) - -(import '(java.util.concurrent Executors LinkedBlockingQueue)) - -(defn pmap - ([f coll] - (let [nthreads (.. Runtime (getRuntime) (availableProcessors)) - exec (. Executors (newFixedThreadPool nthreads)) - todo (ref (seq coll)) - out (ref 0) - q (new LinkedBlockingQueue) - produce (fn [] - (let [job (sync nil - (when @todo - (let [item (first @todo)] - (alter todo rest) - (commute out inc) - (list item))))] - (when job - (. q (put (f (first job)))) - (recur)))) - tasks (doseq dnu (map (fn [task] - (. exec (submit #^java.util.concurrent.Callable task))) - (replicate nthreads produce))) - consume (fn thisfn [] - (if (sync nil (and (or @todo (pos? @out)) - (commute out dec))) - (fnseq (. q (take)) thisfn) - (do - (. exec (shutdown)) - (doseq x tasks) - nil)))] - (consume))) - ([f coll & colls] - (pmap (fn [items] (apply f items)) - (let [encl-fn (fn thisfn [collseq] - (when (every? seq collseq) - (lazy-cons (map first collseq) - (thisfn (map rest collseq)))))] - (encl-fn (cons coll colls)))))) - -(defn macroexpand-1 - "If form represents a macro form, returns its expansion, - else returns form." - [form] - (. clojure.lang.Compiler (macroexpand1 form))) - -(defn macroexpand - "Repeatedly calls macroexpand-1 on form until it no longer - represents a macro form, then returns it. Note neither - macroexpand-1 nor macroexpand expand macros in subforms." - [form] - (let [ex (macroexpand-1 form)] - (if (identical? ex form) - form - (macroexpand ex)))) - -(defn create-struct - "Returns a structure basis object." - [& keys] - (. clojure.lang.PersistentStructMap (createSlotMap keys))) - -(defmacro defstruct - "Same as (def name (create-struct keys...))" - [name & keys] - `(def ~name (create-struct ~@keys))) - -(defn struct-map - "Returns a new structmap instance with the keys of the - structure-basis. keyvals may contain all, some or none of the basis - keys - where values are not supplied they will default to nil. - keyvals can also contain keys not in the basis." - [s & inits] - (. clojure.lang.PersistentStructMap (create s inits))) - -(defn struct - "Returns a new structmap instance with the keys of the - structure-basis. vals must be supplied for basis keys in order - - where values are not supplied they will default to nil." - [s & vals] - (. clojure.lang.PersistentStructMap (construct s vals))) - -(defn accessor - "Returns a fn that, given an instance of a structmap with the basis, - returns the value at the key. The key must be in the basis. The - returned function should be (slightly) more efficient than using - get, but such use of accessors should be limited to known - performance-critical areas." - [s key] - (. clojure.lang.PersistentStructMap (getAccessor s key))) - -(defn subvec - "Returns a persistent vector of the items in vector from - start (inclusive) to end (exclusive). If end is not supplied, - defaults to (count vector). This operation is O(1) and very fast, as - the resulting vector shares structure with the original and no - trimming is done." - ([v start] - (subvec v start (count v))) - ([v start end] - (. clojure.lang.RT (subvec v start end)))) - -(defn load - "Sequentially read and evaluate the set of forms contained in the - stream/file" - [rdr] (. clojure.lang.Compiler (load rdr))) - -(defn resultset-seq - "Creates and returns a lazy sequence of structmaps corresponding to - the rows in the java.sql.ResultSet rs" - [#^java.sql.ResultSet rs] - (let [rsmeta (. rs (getMetaData)) - idxs (range 1 (inc (. rsmeta (getColumnCount)))) - keys (map (comp keyword (memfn toLowerCase)) - (map (fn [i] (. rsmeta (getColumnName i))) idxs)) - row-struct (apply create-struct keys) - row-values (fn [] (map (fn [#^Integer i] (. rs (getObject i))) idxs)) - rows (fn thisfn [] - (when (. rs (next)) - (lazy-cons (apply struct row-struct (row-values)) (thisfn))))] - (rows))) - -(defn set - "Returns a set of the distinct elements of coll." - [coll] (apply hash-set coll)) - -(defn #^{:private true} - filter-key [keyfn pred amap] - (loop [ret {} es (seq amap)] - (if es - (if (pred (keyfn (first es))) - (recur (assoc ret (key (first es)) (val (first es))) (rest es)) - (recur ret (rest es))) - ret))) - -(defn find-ns - "Returns the namespace named by the symbol or nil if it doesn't exist." - [sym] (. clojure.lang.Namespace (find sym))) - -(defn create-ns - "Create a new namespace named by the symbol if one doesn't already - exist, returns it or the already-existing namespace of the same - name." - [sym] (. clojure.lang.Namespace (findOrCreate sym))) - -(defn remove-ns - "Removes the namespace named by the symbol. Use with caution. - Cannot be used to remove the clojure namespace." - [sym] (. clojure.lang.Namespace (remove sym))) - -(defn all-ns - "Returns a sequence of all namespaces." - [] (. clojure.lang.Namespace (all))) - -(defn ns-name - "Returns the name of the namespace, a symbol." - [#^clojure.lang.Namespace ns] - (. ns (getName))) - -(defn ns-map - "Returns a map of all the mappings for the namespace." - [#^clojure.lang.Namespace ns] - (. ns (getMappings))) - -(defn ns-unmap - "Removes the mappings for the symbol from the namespace." - [#^clojure.lang.Namespace ns sym] - (. ns (unmap sym))) - -;(defn export [syms] -; (doseq sym syms -; (.. *ns* (intern sym) (setExported true)))) - -(defn ns-publics - "Returns a map of the public intern mappings for the namespace." - [#^clojure.lang.Namespace ns] - (filter-key val (fn [#^clojure.lang.Var v] (and (instance? clojure.lang.Var v) - (= ns (. v ns)) - (. v (isPublic)))) - (ns-map ns))) - -(defn ns-imports - "Returns a map of the import mappings for the namespace." - [#^clojure.lang.Namespace ns] - (filter-key val (partial instance? Class) (ns-map ns))) - -(defn refer - "refers to all public vars of ns, subject to filters. - filters can include at most one each of: - - :exclude list-of-symbols - :only list-of-symbols - :rename map-of-fromsymbol-tosymbol - - For each public interned var in the namespace named by the symbol, - adds a mapping from the name of the var to the var to the current - namespace. Throws an exception if name is already mapped to - something else in the current namespace. Filters can be used to - select a subset, via inclusion or exclusion, or to provide a mapping - to a symbol different from the var's name, in order to prevent - clashes." - [ns-sym & filters] - (let [ns (or (find-ns ns-sym) (throw (new Exception (str "No namespace: " ns-sym)))) - fs (apply hash-map filters) - nspublics (ns-publics ns) - rename (or (:rename fs) {}) - exclude (set (:exclude fs)) - to-do (or (:only fs) (keys nspublics))] - (doseq sym to-do - (when-not (exclude sym) - (let [v (nspublics sym)] - (when-not v - (throw (new java.lang.IllegalAccessError (str sym " is not public")))) - (. *ns* (refer (or (rename sym) sym) v))))))) - -(defn ns-refers - "Returns a map of the refer mappings for the namespace." - [#^clojure.lang.Namespace ns] - (filter-key val (fn [#^clojure.lang.Var v] (and (instance? clojure.lang.Var v) - (not= ns (. v ns)))) - (ns-map ns))) - -(defn ns-interns - "Returns a map of the intern mappings for the namespace." - [#^clojure.lang.Namespace ns] - (filter-key val (fn [#^clojure.lang.Var v] (and (instance? clojure.lang.Var v) - (= ns (. v ns)))) - (ns-map ns))) - -(defn take-nth - "Returns a lazy seq of every nth item in coll." - [n coll] - (when (seq coll) - (lazy-cons (first coll) (take-nth n (drop n coll))))) - -(defn interleave - "Returns a lazy seq of the first item in each coll, then the second - etc." - [& colls] - (apply concat (apply map list colls))) - -(defn var-get - "Gets the value in the var object" - [#^clojure.lang.Var x] (. x (get))) - -(defn var-set - "Sets the value in the var object to val. The var must be - thread-locally bound." - [#^clojure.lang.Var x val] (. x (set val))) - -(defmacro with-local-vars - "varbinding=> symbol init-expr - - Executes the exprs in a context in which the symbols are bound to - vars with per-thread bindings to the init-exprs. The symbols refer - to the var objects themselves, and must be accessed with var-get and - var-set" - [name-vals-vec & body] - `(let [~@(interleave (take-nth 2 name-vals-vec) - (repeat '(. clojure.lang.Var (create))))] - (. clojure.lang.Var (pushThreadBindings (hash-map ~@name-vals-vec))) - (try - ~@body - (finally (. clojure.lang.Var (popThreadBindings)))))) - -(defn ns-resolve - "Returns the var or Class to which a symbol will be resolved in the - namespace, else nil. Note that if the symbol is fully qualified, - the var/Class to which it resolves need not be present in the - namespace." - [ns sym] - (. clojure.lang.Compiler (maybeResolveIn ns sym))) - -(defn resolve - "same as (ns-resolve *ns* symbol)" - [sym] (ns-resolve *ns* sym)) - -(defn array-map - "Constructs an array-map." - ([] (. clojure.lang.PersistentArrayMap EMPTY)) - ([& keyvals] (new clojure.lang.PersistentArrayMap (to-array keyvals)))) - -(defn nthrest - "Returns the nth rest of coll, (seq coll) when n is 0." - [coll n] - (loop [n n xs (seq coll)] - (if (and xs (pos? n)) - (recur (dec n) (rest xs)) - xs))) - -(defn symbol? - "Return true if x is a Symbol" - [x] (instance? clojure.lang.Symbol x)) - -(defn keyword? - "Return true if x is a Keyword" - [x] (instance? clojure.lang.Keyword x)) - -;redefine let and loop with destructuring -(defn destructure [bindings] - (let [bmap (apply array-map bindings) - pb (fn pb [bvec b v] - (let [pvec - (fn [bvec b val] - (let [gvec (gensym "vec__")] - (loop [ret (-> bvec (conj gvec) (conj val)) - n 0 - bs b - seen-rest? false] - (if bs - (let [firstb (first bs)] - (cond - (= firstb '&) (recur (pb ret (second bs) (list `nthrest gvec n)) - n - (rrest bs) - true) - (= firstb :as) (pb ret (second bs) gvec) - :else (if seen-rest? - (throw (new Exception "Unsupported binding form, only :as can follow & parameter")) - (recur (pb ret firstb (list `nth gvec n nil)) - (inc n) - (rest bs) - seen-rest?)))) - ret)))) - pmap - (fn [bvec b v] - (let [gmap (or (:as b) (gensym "map__")) - defaults (:or b)] - (loop [ret (-> bvec (conj gmap) (conj v)) - bes (reduce - (fn [bes entry] - (reduce #(assoc %1 %2 ((val entry) %2)) - (dissoc bes (key entry)) - ((key entry) bes))) - (dissoc b :as :or) - {:keys #(keyword (str %)), :strs str, :syms #(list `quote %)})] - (if bes - (let [bb (key (first bes)) - bk (val (first bes)) - has-default (contains? defaults bb)] - (recur (pb ret bb (if has-default - (list `get gmap bk (defaults bb)) - (list `get gmap bk))) - (rest bes))) - ret))))] - (cond - (symbol? b) (-> bvec (conj b) (conj v)) - (vector? b) (pvec bvec b v) - (map? b) (pmap bvec b v) - :else (throw (new Exception (str "Unsupported binding form: " b)))))) - process-entry (fn [bvec b] (pb bvec (key b) (val b)))] - (if (every? symbol? (keys bmap)) - bindings - (reduce process-entry [] bmap)))) - -(defmacro let - "Evaluates the exprs in a lexical context in which the symbols in - the binding-forms are bound to their respective init-exprs or parts - therein." - [bindings & body] - `(let* ~(destructure bindings) ~@body)) - -;redefine fn with destructuring -(defmacro fn - "(fn name? [params* ] exprs*) - (fn name? ([params* ] exprs*)+) - - params => positional-params* , or positional-params* & rest-param - positional-param => binding-form - rest-param => binding-form - name => symbol - - Defines a function" - [& sigs] - (let [name (if (symbol? (first sigs)) (first sigs) nil) - sigs (if name (rest sigs) sigs) - sigs (if (vector? (first sigs)) (list sigs) sigs) - psig (fn [sig] - (let [[params & body] sig] - (if (every? symbol? params) - sig - (loop [params params - new-params [] - lets []] - (if params - (if (symbol? (first params)) - (recur (rest params) (conj new-params (first params)) lets) - (let [gparam (gensym "p__")] - (recur (rest params) (conj new-params gparam) - (-> lets (conj (first params)) (conj gparam))))) - `(~new-params - (let ~lets - ~@body))))))) - new-sigs (map psig sigs)] - (with-meta - (if name - (list* 'fn* name new-sigs) - (cons 'fn* new-sigs)) - *macro-meta*))) - -(defmacro loop - "Evaluates the exprs in a lexical context in which the symbols in - the binding-forms are bound to their respective init-exprs or parts - therein. Acts as a recur target." - [bindings & body] - (let [db (destructure bindings)] - (if (= db bindings) - `(loop* ~bindings ~@body) - (let [vs (take-nth 2 (drop 1 bindings)) - bs (take-nth 2 bindings) - gs (map (fn [b] (if (symbol? b) b (gensym))) bs) - bfs (reduce (fn [ret [b v g]] - (if (symbol? b) - (conj ret g v) - (conj ret g v b g))) - [] (map vector bs vs gs))] - `(let ~bfs - (loop* ~(vec (interleave gs gs)) - (let ~(vec (interleave bs gs)) - ~@body))))))) - -(defmacro when-first - "Same as (when (seq xs) (let [x (first xs)] body))" - [x xs & body] - `(when (seq ~xs) - (let [~x (first ~xs)] - ~@body))) - -(defmacro lazy-cat - "Expands to code which yields a lazy sequence of the concatenation - of the supplied colls. Each coll expr is not evaluated until it is - needed." - ([coll] `(seq ~coll)) - ([coll & colls] - `(let [iter# (fn iter# [coll#] - (if (seq coll#) - (lazy-cons (first coll#) (iter# (rest coll#))) - (lazy-cat ~@colls)))] - (iter# ~coll)))) - - - -(defmacro for - "List comprehension. Takes a vector of one or more - binding-form/collection-expr pairs, each followed by an optional filtering - :when/:while expression (:when test or :while test), and yields a - lazy sequence of evaluations of expr. Collections are iterated in a - nested fashion, rightmost fastest, and nested coll-exprs can refer to - bindings created in prior binding-forms. - - (take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))" - ([seq-exprs expr] - (let [pargs (fn [xs] - (loop [ret [] - [b e & [w f & wr :as r] :as xs] (seq xs)] - (if xs - (cond - (= w :when) (recur (conj ret {:b b :e e :f f :w :when}) wr) - (= w :while) (recur (conj ret {:b b :e e :f f :w :while}) wr) - :else (recur (conj ret {:b b :e e :f true :w :while}) r)) - (seq ret)))) - emit (fn emit [[{b :b f :f w :w} & [{ys :e} :as rses]]] - (let [giter (gensym "iter__") gxs (gensym "s__")] - `(fn ~giter [~gxs] - (when-first ~b ~gxs - (if ~f - ~(if rses - `(let [iterys# ~(emit rses)] - (lazy-cat (iterys# ~ys) - (~giter (rest ~gxs)))) - `(lazy-cons ~expr (~giter (rest ~gxs)))) - ~(if (= w :when) - `(recur (rest ~gxs)) - nil))))))] - `(let [iter# ~(emit (pargs seq-exprs))] - (iter# ~(second seq-exprs)))))) - -(defmacro comment - "Ignores body, yields nil" - [& body]) - -(defmacro with-out-str - "Evaluates exprs in a context in which *out* is bound to a fresh - StringWriter. Returns the string created by any nested printing - calls." - [& body] - `(let [s# (new java.io.StringWriter)] - (binding [*out* s#] - ~@body - (str s#)))) - -(defn pr-str - "pr to a string, returning it" - [& xs] - (with-out-str - (apply pr xs))) - -(defn prn-str - "prn to a string, returning it" - [& xs] - (with-out-str - (apply prn xs))) - -(defn print-str - "print to a string, returning it" - [& xs] - (with-out-str - (apply print xs))) - -(defn println-str - "println to a string, returning it" - [& xs] - (with-out-str - (apply println xs))) - -(defmacro assert - "Evaluates expr and throws an exception if it does not evaluate to - logical true." - [x] - `(when-not ~x - (throw (new Exception (str "Assert failed: " (pr-str '~x)))))) - -(defn test - "test [v] finds fn at key :test in var metadata and calls it, - presuming failure will throw exception" - [v] - (let [f (:test ^v)] - (if f - (do (f) :ok) - :no-test))) - -(defn re-pattern - "Returns an instance of java.util.regex.Pattern, for use, e.g. in - re-matcher." - {:tag java.util.regex.Pattern} - [s] (. java.util.regex.Pattern (compile s))) - -(defn re-matcher - "Returns an instance of java.util.regex.Matcher, for use, e.g. in - re-find." - {:tag java.util.regex.Matcher} - [#^java.util.regex.Pattern re s] - (. re (matcher s))) - -(defn re-groups - "Returns the groups from the most recent match/find. If there are no - nested groups, returns a string of the entire match. If there are - nested groups, returns a vector of the groups, the first element - being the entire match." - [#^java.util.regex.Matcher m] - (let [gc (. m (groupCount))] - (if (zero? gc) - (. m (group)) - (loop [ret [] c 0] - (if (<= c gc) - (recur (conj ret (. m (group c))) (inc c)) - ret))))) - -(defn re-seq - "Returns a lazy sequence of successive matches of pattern in string, - using java.util.regex.Matcher.find(), each such match processed with - re-groups." - [#^java.util.regex.Pattern re s] - (let [m (re-matcher re s)] - ((fn step [] - (when (. m (find)) - (lazy-cons (re-groups m) (step))))))) - -(defn re-matches - "Returns the match, if any, of string to pattern, using - java.util.regex.Matcher.matches(). Uses re-groups to return the - groups." - [#^java.util.regex.Pattern re s] - (let [m (re-matcher re s)] - (when (. m (matches)) - (re-groups m)))) - - -(defn re-find - "Returns the next regex match, if any, of string to pattern, using - java.util.regex.Matcher.find(). Uses re-groups to return the - groups." - ([#^java.util.regex.Matcher m] - (when (. m (find)) - (re-groups m))) - ([#^java.util.regex.Pattern re s] - (let [m (re-matcher re s)] - (re-find m)))) - -(defn rand - "Returns a random floating point number between 0 (inclusive) and - 1 (exclusive)." - ([] (. Math (random))) - ([n] (* n (rand)))) - -(defn rand-int - "Returns a random integer between 0 (inclusive) and n (exclusive)." - [n] (int (rand n))) - -(defmacro defn- - "same as defn, yielding non-public def" - [name & decls] - (list* `defn (with-meta name (assoc (meta name) :private true)) decls)) - -(defn print-doc [v] - (println "-------------------------") - (println (str (ns-name (:ns ^v)) "/" (:name ^v))) - (prn (:arglists ^v)) - (when (:macro ^v) - (println "Macro")) - (println " " (:doc ^v))) - -(defn find-doc - "Prints documentation for any var whose documentation or name - contains a match for re-string" - [re-string] - (let [re (re-pattern re-string)] - (dorun (for [ns (all-ns) - v (sort-by (comp :name meta) (vals (ns-interns ns))) - :when (and (:doc ^v) - (or (re-find (re-matcher re (:doc ^v))) - (re-find (re-matcher re (str (:name ^v))))))] - (print-doc v))))) - -(defmacro doc - "Prints documentation for the var named by varname" - [varname] - `(print-doc (var ~varname))) - -(defn tree-seq - "returns a lazy sequence of the nodes in a tree, via a depth-first walk. - branch? must be a fn of one arg that returns true if passed a node - that can have children (but may not). children must be a fn of one - arg that returns a sequence of the children. Will only be called on - nodes for which branch? returns true. Root is the root node of the - tree, must be a branch." - [branch? children root] - (let [walk (fn walk [nodes] - (when-first node nodes - (lazy-cons - node - (if (branch? node) - (lazy-cat (walk (children node)) - (walk (rest nodes))) - (walk (rest nodes))))))] - (lazy-cons root (walk (children root))))) - -(defn file-seq - "A tree seq on java.io.Files" - [dir] - (tree-seq - (fn [#^java.io.File f] (. f (isDirectory))) - (fn [#^java.io.File d] (seq (. d (listFiles)))) - dir)) - -(defn xml-seq - "A tree seq on the xml elements as per xml/parse" - [root] - (tree-seq - (complement string?) - (comp seq :content) - root)) - -(defn special-symbol? - "Returns true if s names a special form" - [s] - (contains? (. clojure.lang.Compiler specials) s)) - -(defn var? - "Returns true if v is of type clojure.lang.Var" - [v] (instance? clojure.lang.Var v)) - -(defn class - "Returns the Class of x" - [#^Object x] (. x (getClass))) - -(defn slurp - "Reads the file named by f into a string and returns it." - [#^String f] - (with-open r (new java.io.BufferedReader (new java.io.FileReader f)) - (let [sb (new StringBuilder)] - (loop [c (. r (read))] - (if (neg? c) - (str sb) - (do - (. sb (append (char c))) - (recur (. r (read))))))))) - -(defn subs - "Returns the substring of s beginning at start inclusive, and ending - at end (defaults to length of string), exclusive." - ([#^String s start] (. s (substring start))) - ([#^String s start end] (. s (substring start end)))) - -(defn max-key - "Returns the x for which (k x), a number, is greatest." - ([k x] x) - ([k x y] (if (> (k x) (k y)) x y)) - ([k x y & more] - (reduce #(max-key k %1 %2) (max-key k x y) more))) - -(defn min-key - "Returns the x for which (k x), a number, is least." - ([k x] x) - ([k x y] (if (< (k x) (k y)) x y)) - ([k x y & more] - (reduce #(min-key k %1 %2) (min-key k x y) more))) - -(defn distinct - "Returns a lazy sequence of the elements of coll with duplicates removed" - [coll] - (let [step (fn step [[f & r :as xs] seen] - (when xs - (if (seen f) (recur r seen) - (lazy-cons f (step r (conj seen f))))))] - (step (seq coll) #{}))) - -(defmacro if-let - "if test is true, evaluates then with binding-form bound to the value of test, if not, yields else" - ([binding-form test then] - `(if-let ~binding-form ~test ~then nil)) - ([binding-form test then else] - `(let [temp# ~test] - (if temp# - (let [~binding-form temp#] - ~then) - ~else)))) - -(defmacro when-let - "when test is true, evaluates body with binding-form bound to the value of test" - [binding-form test & body] - `(let [temp# ~test] - (when temp# - (let [~binding-form temp#] - ~@body)))) - -(defn replace - "Given a map of replacement pairs and a vector/collection, returns a - vector/seq with any elements = a key in smap replaced with the - corresponding val in smap" - [smap coll] - (if (vector? coll) - (reduce (fn [v i] - (if-let e (find smap (nth v i)) - (assoc v i (val e)) - v)) - coll (range (count coll))) - (map #(if-let e (find smap %) (val e) %) coll))) - -(defmacro dosync - "Runs the exprs (in an implicit do) in a transaction that encompasses - exprs and any nested calls. Starts a transaction if none is already - running on this thread. Any uncaught exception will abort the - transaction and flow out of dosync. The exprs may be run more than - once, but any effects on Refs will be atomic." - [& exprs] - `(sync nil ~@exprs)) - -(defmacro with-precision - "Sets the precision and rounding mode to be used for BigDecimal operations. - - Usage: (with-precision 10 (/ 1M 3)) - or: (with-precision 10 :rounding HALF_DOWN (/ 1M 3)) - - The rounding mode is one of CEILING, FLOOR, HALF_UP, HALF_DOWN, - HALF_EVEN, UP, DOWN and UNNECESSARY; it defaults to HALF_UP." - [precision & exprs] - (let [[body rm] (if (= (first exprs) :rounding) - [(rest (rest exprs)) - `((. java.math.RoundingMode ~(second exprs)))] - [exprs nil])] - `(binding [*math-context* (java.math.MathContext. ~precision ~@rm)] - ~@body))) - -(defn bound-fn - {:private true} - [#^clojure.lang.Sorted sc test key] - (fn [e] - (test (.. sc comparator (compare (. sc entryKey e) key)) 0))) - -(defn subseq - "sc must be a sorted collection, test(s) one of <, <=, > or - >=. Returns a seq of those entries with keys ek for - which (test (.. sc comparator (compare ek key)) 0) is true" - ([#^clojure.lang.Sorted sc test key] - (let [include (bound-fn sc test key)] - (if (#{> >=} test) - (when-let [e :as s] (. sc seqFrom key true) - (if (include e) s (rest s))) - (take-while include (. sc seq true))))) - ([#^clojure.lang.Sorted sc start-test start-key end-test end-key] - (when-let [e :as s] (. sc seqFrom start-key true) - (take-while (bound-fn sc end-test end-key) - (if ((bound-fn sc start-test start-key) e) s (rest s)))))) - -(defn rsubseq - "sc must be a sorted collection, test(s) one of <, <=, > or - >=. Returns a reverse seq of those entries with keys ek for - which (test (.. sc comparator (compare ek key)) 0) is true" - ([#^clojure.lang.Sorted sc test key] - (let [include (bound-fn sc test key)] - (if (#{< <=} test) - (when-let [e :as s] (. sc seqFrom key false) - (if (include e) s (rest s))) - (take-while include (. sc seq false))))) - ([#^clojure.lang.Sorted sc start-test start-key end-test end-key] - (when-let [e :as s] (. sc seqFrom end-key false) - (take-while (bound-fn sc start-test start-key) - (if ((bound-fn sc end-test end-key) e) s (rest s)))))) - -(defn repeatedly - "Takes a function of no args, presumably with side effects, and returns an infinite - lazy sequence of calls to it" - [f] (lazy-cons (f) (repeatedly f))) - -(defn add-classpath - "Adds the url (String or URL object) to the classpath per URLClassLoader.addURL" - [url] (. clojure.lang.RT addURL url)) - - - -(defn hash - "Returns the hash code of its argument" - [x] (. clojure.lang.Util (hash x))) - -(defn interpose - "Returns a lazy seq of the elements of coll separated by sep" - [sep coll] (drop 1 (interleave (repeat sep) coll))) - -(defn partition - "Returns a lazy sequence of lists of n items each, at offsets step - apart. If step is not supplied, defaults to n, i.e. the partitions - do not overlap." - ([n coll] - (partition n n coll)) - ([n step coll] - (when (seq coll) - (let [p (take n coll)] - (when (= n (count p)) - (lazy-cons p (partition n step (drop step coll)))))))) - -(defmacro definline - "Experimental - like defmacro, except defines a named function whose - body is the expansion, calls to which may be expanded inline as if - it were a macro" - [name & decl] - (let [[args expr] (drop-while (comp not vector?) decl) - inline (eval (list 'fn args expr))] - `(do - (defn ~name ~args ~(apply inline args)) - (let [v# (var ~name)] - (.setMeta v# (assoc ^v# :inline ~inline)))))) - -(defn empty - "Returns an empty collection of the same category as coll, or nil" - [#^clojure.lang.IPersistentCollection coll] - (.empty coll)) - -(defmacro amap - "Maps an expression across an array a, using an index named idx, and - return value named ret, initialized to a clone of a, then setting each element of - ret to the evaluation of expr, returning the new array ret." - [a idx ret expr] - `(let [a# ~a - ~ret (aclone a#)] - (loop [~idx (int 0)] - (if (< ~idx (alength a#)) - (do - (aset ~ret ~idx ~expr) - (recur (unchecked-inc ~idx))) - ~ret)))) - -(defmacro areduce - "Reduces an expression across an array a, using an index named idx, - and return value named ret, initialized to init, setting ret to the evaluation of expr at - each step, returning ret." - [a idx ret init expr] - `(let [a# ~a] - (loop [~idx (int 0) ~ret ~init] - (if (< ~idx (alength a#)) - (recur (unchecked-inc ~idx) ~expr) - ~ret)))) - -(defn float-array - "Creates an array of floats" - {:inline (fn [& args] `(. clojure.lang.Numbers float_array ~@args)) - :inline-arities #{1 2}} - ([size-or-seq] (. clojure.lang.Numbers float_array size-or-seq)) - ([size init-val-or-seq] (. clojure.lang.Numbers float_array size init-val-or-seq))) - -(defn double-array - "Creates an array of doubles" - {:inline (fn [& args] `(. clojure.lang.Numbers double_array ~@args)) - :inline-arities #{1 2}} - ([size-or-seq] (. clojure.lang.Numbers double_array size-or-seq)) - ([size init-val-or-seq] (. clojure.lang.Numbers double_array size init-val-or-seq))) - -(defn int-array - "Creates an array of ints" - {:inline (fn [& args] `(. clojure.lang.Numbers int_array ~@args)) - :inline-arities #{1 2}} - ([size-or-seq] (. clojure.lang.Numbers int_array size-or-seq)) - ([size init-val-or-seq] (. clojure.lang.Numbers int_array size init-val-or-seq))) - -(defn long-array - "Creates an array of ints" - {:inline (fn [& args] `(. clojure.lang.Numbers long_array ~@args)) - :inline-arities #{1 2}} - ([size-or-seq] (. clojure.lang.Numbers long_array size-or-seq)) - ([size init-val-or-seq] (. clojure.lang.Numbers long_array size init-val-or-seq))) - -(definline floats - "Casts to float[]" - [xs] `(. clojure.lang.Numbers floats ~xs)) - -(definline ints - "Casts to int[]" - [xs] `(. clojure.lang.Numbers ints ~xs)) - -(definline doubles - "Casts to double[]" - [xs] `(. clojure.lang.Numbers doubles ~xs)) - -(definline longs - "Casts to long[]" - [xs] `(. clojure.lang.Numbers longs ~xs)) - -(import '(java.util.concurrent BlockingQueue LinkedBlockingQueue)) - -(defn seque - "Creates a queued seq on another (presumably lazy) seq s. The queued - seq will produce a concrete seq in the background, and can get up to - n items ahead of the consumer. n-or-q can be an integer n buffer - size, or an instance of java.util.concurrent BlockingQueue. Note - that reading from a seque can block if the reader gets ahead of the - producer." - ([s] (seque 100 s)) - ([n-or-q s] - (let [#^BlockingQueue q (if (instance? BlockingQueue n-or-q) - n-or-q - (LinkedBlockingQueue. (int n-or-q))) - NIL (Object.) ;nil sentinel since LBQ doesn't support nils - agt (agent (seq s)) - fill (fn [s] - (try - (loop [[x & xs :as s] s] - (if s - (if (.offer q (if (nil? x) NIL x)) - (recur xs) - s) - (.put q q))) ; q itself is eos sentinel - (catch Exception e - (.put q q) - (throw e)))) - drain (fn drain [] - (let [x (.take q)] - (if (identical? x q) ;q itself is eos sentinel - @agt ;will be nil - touch agent just to propagate errors - (do - (send-off agt fill) - (lazy-cons (if (identical? x NIL) nil x) (drain))))))] - (send-off agt fill) - (drain))))
\ No newline at end of file diff --git a/src/genclass.clj b/src/genclass.clj deleted file mode 100644 index cdc09845..00000000 --- a/src/genclass.clj +++ /dev/null @@ -1,517 +0,0 @@ -; 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) - -(import '(java.lang.reflect Modifier Constructor) - '(clojure.asm ClassWriter ClassVisitor Opcodes Type) - '(clojure.asm.commons Method GeneratorAdapter) - '(clojure.lang IPersistentMap)) - -;(defn method-sig [#^java.lang.reflect.Method meth] -; [(. meth (getName)) (seq (. meth (getParameterTypes)))]) - -(defn- non-private-methods [#^Class c] - (loop [mm {} - considered #{} - c c] - (if c - (let [[mm considered] - (loop [mm mm - considered considered - meths (concat - (seq (. c (getDeclaredMethods))) - (seq (. c (getMethods))))] - (if meths - (let [#^java.lang.reflect.Method meth (first meths) - mods (. meth (getModifiers)) - mk (method-sig meth)] - (if (or (considered mk) - (. Modifier (isPrivate mods)) - (. Modifier (isStatic mods)) - (. Modifier (isFinal mods)) - (= "finalize" (.getName meth))) - (recur mm (conj considered mk) (rest meths)) - (recur (assoc mm mk meth) (conj considered mk) (rest meths)))) - [mm considered]))] - (recur mm considered (. c (getSuperclass)))) - mm))) - -(defn- ctor-sigs [super] - (for [#^Constructor ctor (. super (getDeclaredConstructors)) - :when (not (. Modifier (isPrivate (. ctor (getModifiers)))))] - (apply vector (. ctor (getParameterTypes))))) - -(defn- escape-class-name [c] - (.. (.getSimpleName c) - (replace "[]" "<>"))) - -(defn- overload-name [mname pclasses] - (if (seq pclasses) - (apply str mname (interleave (repeat \-) - (map escape-class-name pclasses))) - (str mname "-void"))) - -;(distinct (map first(keys (mapcat non-private-methods [Object IPersistentMap])))) - -(defn gen-class - "Generates compiled bytecode for a class with the given - package-qualified cname (which, as all names in these parameters, can - be a string or symbol). The gen-class construct contains no - implementation, as the implementation will be dynamically sought by - the generated class in functions in a corresponding Clojure - namespace. Given a generated class org.mydomain.MyClass, methods - will be implemented that look for same-named functions in a Clojure - namespace called org.domain.MyClass. The init and main - functions (see below) will be found similarly. The static - initializer for the generated class will attempt to load the Clojure - support code for the class as a resource from the claspath, e.g. in - the example case, org/mydomain/MyClass.clj - - Returns a map containing :name and :bytecode. Most uses will be - satisfied by the higher-level gen-and-load-class and - gen-and-store-class functions, which generate and immediately load, - or generate and store to disk, respectively. - - Options should be a set of key/value pairs, all of which are optional: - - :extends aclass - - Specifies the superclass, the non-private methods of which will be - overridden by the class. If not provided, defaults to Object. - - :implements [interface ...] - - One or more interfaces, the methods of which will be implemented by the class. - - :init name - - If supplied, names a function that will be called with the arguments - to the constructor. Must return [ [superclass-constructor-args] state] - If not supplied, the constructor args are passed directly to - the superclass constructor and the state will be nil - - :constructors {[param-types] [super-param-types], ...} - - By default, constructors are created for the generated class which - match the signature(s) of the constructors for the superclass. This - parameter may be used to explicitly specify constructors, each entry - providing a mapping from a constructor signature to a superclass - constructor signature. When you supply this, you must supply an :init - specifier. - - :methods [ [name [param-types] return-type], ...] - - The generated class automatically defines all of the non-private - methods of its superclasses/interfaces. This parameter can be used - to specify the signatures of additional methods of the generated - class. Static methods can be specified with #^{:static true} in the - signature's metadata. Do not repeat superclass/interface signatures - here. - - :main boolean - - If supplied and true, a static public main function will be - generated. It will pass each string of the String[] argument as a - separate argument to a function called 'main. - - :factory name - - If supplied, a (set of) public static factory function(s) will be - created with the given name, and the same signature(s) as the - constructor(s). - - :state name - - If supplied, a public final instance field with the given name will be - created. You must supply an :init function in order to provide a - value for the state. Note that, though final, the state can be a ref - or agent, supporting the creation of Java objects with transactional - or asynchronous mutation semantics. - - :exposes {protected-field-name {:get name :set name}, ...} - - Since the implementations of the methods of the generated class - occur in Clojure functions, they have no access to the inherited - protected fields of the superclass. This parameter can be used to - generate public getter/setter methods exposing the protected field(s) - for use in the implementation." - - [cname & options] - (let [name (str cname) - {:keys [extends implements constructors methods main factory state init exposes]} (apply hash-map options) - super (or extends Object) - interfaces implements - supers (cons super (seq interfaces)) - ctor-sig-map (or constructors (zipmap (ctor-sigs super) (ctor-sigs super))) - cv (new ClassWriter (. ClassWriter COMPUTE_MAXS)) - cname (. name (replace "." "/")) - ctype (. Type (getObjectType cname)) - iname (fn [c] (.. Type (getType c) (getInternalName))) - totype (fn [c] (. Type (getType c))) - to-types (fn [cs] (if (pos? (count cs)) - (into-array (map totype cs)) - (make-array Type 0))) - obj-type (totype Object) - arg-types (fn [n] (if (pos? n) - (into-array (replicate n obj-type)) - (make-array Type 0))) - super-type (totype super) - init-name (str init) - factory-name (str factory) - state-name (str state) - main-name "main" - var-name (fn [s] (str s "__var")) - rt-type (totype clojure.lang.RT) - var-type (totype clojure.lang.Var) - ifn-type (totype clojure.lang.IFn) - iseq-type (totype clojure.lang.ISeq) - ex-type (totype java.lang.UnsupportedOperationException) - all-sigs (distinct (concat (map #(let[[m p] (key %)] {m [p]}) (mapcat non-private-methods supers)) - (map (fn [[m p]] {(str m) [p]}) methods))) - sigs-by-name (apply merge-with concat {} all-sigs) - overloads (into {} (filter (fn [[m s]] (rest s)) sigs-by-name)) - var-fields (concat (and init [init-name]) - (and main [main-name]) - (distinct (concat (keys sigs-by-name) - (mapcat (fn [[m s]] (map #(overload-name m %) s)) overloads) - (mapcat (comp (partial map str) vals val) exposes)))) - emit-get-var (fn [gen v] - (let [false-label (. gen newLabel) - end-label (. gen newLabel)] - (. gen getStatic ctype (var-name v) var-type) - (. gen dup) - (. gen invokeVirtual var-type (. Method (getMethod "boolean isBound()"))) - (. gen ifZCmp (. GeneratorAdapter EQ) false-label) - (. gen invokeVirtual var-type (. Method (getMethod "Object get()"))) - (. gen goTo end-label) - (. gen mark false-label) - (. gen pop) - (. gen visitInsn (. Opcodes ACONST_NULL)) - (. gen mark end-label))) - emit-forwarding-method - (fn [mname pclasses rclass as-static else-gen] - (let [ptypes (to-types pclasses) - rtype (totype rclass) - m (new Method mname rtype ptypes) - is-overload (overloads mname) - gen (new GeneratorAdapter (+ (. Opcodes ACC_PUBLIC) (if as-static (. Opcodes ACC_STATIC) 0)) - m nil nil cv) - found-label (. gen (newLabel)) - else-label (. gen (newLabel)) - end-label (. gen (newLabel))] - (. gen (visitCode)) - (when is-overload - (emit-get-var gen (overload-name mname pclasses)) - (. gen (dup)) - (. gen (ifNonNull found-label)) - (. gen (pop))) - (emit-get-var gen mname) - (. gen (dup)) - (. gen (ifNull else-label)) - (when is-overload - (. gen (mark found-label))) - ;if found - (when-not as-static - (. gen (loadThis))) - ;box args - (dotimes i (count ptypes) - (. gen (loadArg i)) - (. clojure.lang.Compiler$HostExpr (emitBoxReturn nil gen (nth pclasses i)))) - ;call fn - (. gen (invokeInterface ifn-type (new Method "invoke" obj-type - (to-types (replicate (+ (count ptypes) - (if as-static 0 1)) - Object))))) - ;(into-array (cons obj-type - ; (replicate (count ptypes) obj-type)))))) - ;unbox return - (. gen (unbox rtype)) - (when (= (. rtype (getSort)) (. Type VOID)) - (. gen (pop))) - (. gen (goTo end-label)) - - ;else call supplied alternative generator - (. gen (mark else-label)) - (. gen (pop)) - - (else-gen gen m) - - (. gen (mark end-label)) - (. gen (returnValue)) - (. gen (endMethod)))) - ] - ;start class definition - (. cv (visit (. Opcodes V1_5) (+ (. Opcodes ACC_PUBLIC) (. Opcodes ACC_SUPER)) - cname nil (iname super) - (when interfaces - (into-array (map iname interfaces))))) - - ;static fields for vars - (doseq v var-fields - (. cv (visitField (+ (. Opcodes ACC_PUBLIC) (. Opcodes ACC_FINAL) (. Opcodes ACC_STATIC)) - (var-name v) - (. var-type getDescriptor) - nil nil))) - - ;instance field for state - (when state - (. cv (visitField (+ (. Opcodes ACC_PUBLIC) (. Opcodes ACC_FINAL)) - state-name - (. obj-type getDescriptor) - nil nil))) - - ;static init to set up var fields and load clj - (let [gen (new GeneratorAdapter (+ (. Opcodes ACC_PUBLIC) (. Opcodes ACC_STATIC)) - (. Method getMethod "void <clinit> ()") - nil nil cv)] - (. gen (visitCode)) - (doseq v var-fields - (. gen push name) - (. gen push v) - (. gen (invokeStatic rt-type (. Method (getMethod "clojure.lang.Var var(String,String)")))) - (. gen putStatic ctype (var-name v) var-type)) - - (. gen push ctype) - (. gen push (str (. name replace \. (. java.io.File separatorChar)) ".clj")) - (. gen (invokeStatic rt-type (. Method (getMethod "void loadResourceScript(Class,String)")))) - - (. gen (returnValue)) - (. gen (endMethod))) - - ;ctors - (doseq [pclasses super-pclasses] ctor-sig-map - (let [ptypes (to-types pclasses) - super-ptypes (to-types super-pclasses) - m (new Method "<init>" (. Type VOID_TYPE) ptypes) - super-m (new Method "<init>" (. Type VOID_TYPE) super-ptypes) - gen (new GeneratorAdapter (. Opcodes ACC_PUBLIC) m nil nil cv) - no-init-label (. gen newLabel) - end-label (. gen newLabel) - nth-method (. Method (getMethod "Object nth(Object,int)")) - local (. gen newLocal obj-type)] - (. gen (visitCode)) - - (if init - (do - (emit-get-var gen init-name) - (. gen dup) - (. gen ifNull no-init-label) - ;box init args - (dotimes i (count pclasses) - (. gen (loadArg i)) - (. clojure.lang.Compiler$HostExpr (emitBoxReturn nil gen (nth pclasses i)))) - ;call init fn - (. gen (invokeInterface ifn-type (new Method "invoke" obj-type - (arg-types (count ptypes))))) - ;expecting [[super-ctor-args] state] returned - (. gen dup) - (. gen push 0) - (. gen (invokeStatic rt-type nth-method)) - (. gen storeLocal local) - - (. gen (loadThis)) - (. gen dupX1) - (dotimes i (count super-pclasses) - (. gen loadLocal local) - (. gen push i) - (. gen (invokeStatic rt-type nth-method)) - (. clojure.lang.Compiler$HostExpr (emitUnboxArg nil gen (nth super-pclasses i)))) - (. gen (invokeConstructor super-type super-m)) - - (if state - (do - (. gen push 1) - (. gen (invokeStatic rt-type nth-method)) - (. gen (putField ctype state-name obj-type))) - (. gen pop)) - - (. gen goTo end-label) - ;no init found - (. gen mark no-init-label) - (. gen (throwException ex-type (str init-name " not defined"))) - (. gen mark end-label)) - (if (= pclasses super-pclasses) - (do - (. gen (loadThis)) - (. gen (loadArgs)) - (. gen (invokeConstructor super-type super-m))) - (throw (new Exception ":init not specified, but ctor and super ctor args differ")))) - - (. gen (returnValue)) - (. gen (endMethod)) - ;factory - (when factory - (let [fm (new Method factory-name ctype ptypes) - gen (new GeneratorAdapter (+ (. Opcodes ACC_PUBLIC) (. Opcodes ACC_STATIC)) - fm nil nil cv)] - (. gen (visitCode)) - (. gen newInstance ctype) - (. gen dup) - (. gen (loadArgs)) - (. gen (invokeConstructor ctype m)) - (. gen (returnValue)) - (. gen (endMethod)))))) - - ;add methods matching supers', if no fn -> call super - (let [mm (non-private-methods super)] - (doseq #^java.lang.reflect.Method meth (vals mm) - (emit-forwarding-method (.getName meth) (.getParameterTypes meth) (.getReturnType meth) false - (fn [gen m] - (. gen (loadThis)) - ;push args - (. gen (loadArgs)) - ;call super - (. gen (visitMethodInsn (. Opcodes INVOKESPECIAL) - (. super-type (getInternalName)) - (. m (getName)) - (. m (getDescriptor))))))) - ;add methods matching interfaces', if no fn -> throw - (doseq #^Class iface interfaces - (doseq #^java.lang.reflect.Method meth (. iface (getMethods)) - (when-not (contains? mm (method-sig meth)) - (emit-forwarding-method (.getName meth) (.getParameterTypes meth) (.getReturnType meth) false - (fn [gen m] - (. gen (throwException ex-type (. m (getName))))))))) - ;extra methods - (doseq [mname pclasses rclass :as msig] methods - (emit-forwarding-method (str mname) pclasses rclass (:static ^msig) - (fn [gen m] - (. gen (throwException ex-type (. m (getName)))))))) - - ;main - (when main - (let [m (. Method getMethod "void main (String[])") - gen (new GeneratorAdapter (+ (. Opcodes ACC_PUBLIC) (. Opcodes ACC_STATIC)) - m nil nil cv) - no-main-label (. gen newLabel) - end-label (. gen newLabel)] - (. gen (visitCode)) - - (emit-get-var gen main-name) - (. gen dup) - (. gen ifNull no-main-label) - (. gen loadArgs) - (. gen (invokeStatic rt-type (. Method (getMethod "clojure.lang.ISeq seq(Object)")))) - (. gen (invokeInterface ifn-type (new Method "applyTo" obj-type - (into-array [iseq-type])))) - (. gen pop) - (. gen goTo end-label) - ;no main found - (. gen mark no-main-label) - (. gen (throwException ex-type (str main-name " not defined"))) - (. gen mark end-label) - (. gen (returnValue)) - (. gen (endMethod)))) - ;field exposers - (doseq [f {getter :get setter :set}] exposes - (let [fld (.getField super (str f)) - ftype (totype (.getType fld))] - (when getter - (let [m (new Method (str getter) ftype (to-types [])) - gen (new GeneratorAdapter (. Opcodes ACC_PUBLIC) m nil nil cv)] - (. gen (visitCode)) - (. gen loadThis) - (. gen getField ctype (str f) ftype) - (. gen (returnValue)) - (. gen (endMethod)))) - (when setter - (let [m (new Method (str setter) (. Type VOID_TYPE) (into-array [ftype])) - gen (new GeneratorAdapter (. Opcodes ACC_PUBLIC) m nil nil cv)] - (. gen (visitCode)) - (. gen loadThis) - (. gen loadArgs) - (. gen putField ctype (str f) ftype) - (. gen (returnValue)) - (. gen (endMethod)))))) - ;finish class def - (. cv (visitEnd)) - {:name name :bytecode (. cv (toByteArray))})) - -(defn gen-and-load-class - "Generates and immediately loads the bytecode for the specified - class. Note that a class generated this way can be loaded only once - - the JVM supports only one class with a given name per - classloader. Subsequent to generation you can import it into any - desired namespaces just like any other class. See gen-class for a - description of the options." - - [name & options] - (let [{:keys [name bytecode]} - (apply gen-class (str name) options)] - (.. clojure.lang.RT ROOT_CLASSLOADER (defineClass (str name) bytecode)))) - -(defn gen-and-save-class - "Generates the bytecode for the named class and stores in a .class - file in a subpath of the supplied path, the directories for which - must already exist. See gen-class for a description of the options" - - [path name & options] - (let [{:keys [name bytecode]} (apply gen-class (str name) options) - file (java.io.File. path (str (. name replace \. (. java.io.File separatorChar)) ".class"))] - (.createNewFile file) - (with-open f (java.io.FileOutputStream. file) - (.write f bytecode)))) - -(comment -;usage -(gen-class - package-qualified-name - ;all below are optional - :extends aclass - :implements [interface ...] - :constructors {[param-types] [super-param-types], } - :methods [[name [param-types] return-type], ] - :main boolean - :factory name - :state name - :init name - :exposes {protected-field {:get name :set name}, }) - -(gen-and-load-class -;(clojure/gen-and-save-class -; "/Users/rich/Downloads" - 'fred.lucy.Ethel - :extends clojure.lang.Box ;APersistentMap - :implements [clojure.lang.IPersistentMap] - :state 'state - ;:constructors {[Object] [Object]} - ;:init 'init - :main true - :factory 'create - :methods [#^{:static true} ['foo [Object] Object] - ['bar [] Object]] - :exposes {'val {:get 'getVal :set 'setVal}}) - -(in-ns 'fred.lucy.Ethel) -(clojure/refer 'clojure :exclude '(assoc seq count cons empty)) -(defn init [n] [[] n]) -(defn foo - ([x] x)) -(defn main [x y] (println x y)) -(in-ns 'user) -(def ethel (new fred.lucy.Ethel__2276 42)) -(def ethel (fred.lucy.Ethel__2276.create 21)) -(fred.lucy.Ethel__2276.main (into-array ["lucy" "ricky"])) -(.state ethel) -(.foo ethel 7) -(.foo ethel) -(.getVal ethel) -(.setVal ethel 12) - -(gen-class org.clojure.MyComparator :implements [Comparator]) -(in-ns 'org.clojure.MyComparator) -(defn compare [this x y] ...) - -(load-file "/Users/rich/dev/clojure/src/genclass.clj") - -(clojure/gen-and-save-class "/Users/rich/dev/clojure/gen/" - 'org.clojure.ClojureServlet - :extends javax.servlet.http.HttpServlet) - -) diff --git a/src/inspector.clj b/src/inspector.clj deleted file mode 100644 index ad0999de..00000000 --- a/src/inspector.clj +++ /dev/null @@ -1,110 +0,0 @@ -; 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 'inspector) -(clojure/refer 'clojure) - -(import '(javax.swing.tree TreeModel) - '(javax.swing.table TableModel) - '(javax.swing JTree JTable JScrollPane JFrame)) - -(defn atom? [x] - (not (instance? clojure.lang.IPersistentCollection x))) - -(defn collection-tag [x] - (cond - (instance? java.util.Map$Entry x) :entry - (instance? clojure.lang.IPersistentMap x) :map - (instance? java.util.Map x) :map - (instance? clojure.lang.Sequential x) :seq - :else :atom)) - -(defmulti is-leaf collection-tag) -(defmulti get-child (fn [parent index] (collection-tag parent))) -(defmulti get-child-count collection-tag) - -(defmethod is-leaf :default [node] - (atom? node)) -(defmethod get-child :default [parent index] - (nth parent index)) -(defmethod get-child-count :default [parent] - (count parent)) - -(defmethod is-leaf :entry [e] - (is-leaf (val e))) -(defmethod get-child :entry [e index] - (get-child (val e) index)) -(defmethod get-child-count :entry [e] - (count (val e))) - -(defmethod is-leaf :map [m] - false) -(defmethod get-child :map [m index] - (nth (seq m) index)) - -(defn tree-model [data] - (proxy [TreeModel] [] - (getRoot [] data) - (addTreeModelListener [treeModelListener]) - (getChild [parent index] - (get-child parent index)) - (getChildCount [parent] - (get-child-count parent)) - (isLeaf [node] - (is-leaf node)) - (valueForPathChanged [path newValue]) - (getIndexOfChild [parent child] - -1) - (removeTreeModelListener [treeModelListener]))) - - -(defn table-model [data] - (let [row1 (first data) - colcnt (count row1) - cnt (count data) - vals (if (instance? clojure.lang.IPersistentMap row1) vals identity)] - (proxy [TableModel] [] - (addTableModelListener [tableModelListener]) - (getColumnClass [columnIndex] Object) - (getColumnCount [] colcnt) - (getColumnName [columnIndex] - (if (instance? clojure.lang.IPersistentMap row1) - (name (nth (keys row1) columnIndex)) - (str columnIndex))) - (getRowCount [] cnt) - (getValueAt [rowIndex columnIndex] - (nth (vals (nth data rowIndex)) columnIndex)) - (isCellEditable [rowIndex columnIndex] false) - (removeTableModelListener [tableModelListener])))) - -(defn inspect-tree - "creates a graphical (Swing) inspector on the supplied hierarchical data" - [data] - (doto (new JFrame "Clojure Inspector") - (add (new JScrollPane (new JTree (tree-model data)))) - (setSize 400 600) - (setVisible true))) - -(defn inspect-table - "creates a graphical (Swing) inspector on the supplied regular - data, which must be a sequential data structure of data structures - of equal length" - [data] - (doto (new JFrame "Clojure Inspector") - (add (new JScrollPane (new JTable (table-model data)))) - (setSize 400 600) - (setVisible true))) - -(comment - -(load-file "src/inspector.clj") -(refer 'inspector) -(inspect-tree {:a 1 :b 2 :c [1 2 3 {:d 4 :e 5 :f [6 7 8]}]}) -(inspect-table [[1 2 3][4 5 6][7 8 9][10 11 12]]) - -)
\ No newline at end of file diff --git a/src/parallel.clj b/src/parallel.clj deleted file mode 100644 index 80e92b81..00000000 --- a/src/parallel.clj +++ /dev/null @@ -1,248 +0,0 @@ -; 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 'parallel) -(clojure/refer 'clojure) - -(comment " -The parallel library wraps the ForkJoin library scheduled for inclusion in JDK 7: - -http://gee.cs.oswego.edu/dl/concurrency-interest/index.html - -You'll need jsr166y.jar in your classpath in order to use this -library. The basic idea is that Clojure collections, and most -efficiently vectors, can be turned into parallel arrays for use by -this library with the function par, although most of the functions -take collections and will call par if needed, so normally you will -only need to call par explicitly in order to attach bound/filter/map -ops. Parallel arrays support the attachment of bounds, filters and -mapping functions prior to realization/calculation, which happens as -the result of any of several operations on the -array (pvec/psort/pfilter-nils/pfilter-dupes). Rather than perform -composite operations in steps, as would normally be done with -sequences, maps and filters are instead attached and thus composed by -providing ops to par. Note that there is an order sensitivity to the -attachments - bounds precede filters precede mappings. All operations -then happen in parallel, using multiple threads and a sophisticated -work-stealing system supported by fork-join, either when the array is -realized, or to perform aggregate operations like preduce/pmin/pmax -etc. A parallel array can be realized into a Clojure vector using -pvec. -") - -(import '(jsr166y.forkjoin ParallelArray ParallelArrayWithBounds ParallelArrayWithFilter - ParallelArrayWithMapping - Ops$Op Ops$BinaryOp Ops$Reducer Ops$Predicate Ops$BinaryPredicate - Ops$IntAndObjectPredicate Ops$IntAndObjectToObject)) - -(defn- op [f] - (proxy [Ops$Op] [] - (op [x] (f x)))) - -(defn- binary-op [f] - (proxy [Ops$BinaryOp] [] - (op [x y] (f x y)))) - -(defn- int-and-object-to-object [f] - (proxy [Ops$IntAndObjectToObject] [] - (op [i x] (f x i)))) - -(defn- reducer [f] - (proxy [Ops$Reducer] [] - (op [x y] (f x y)))) - -(defn- predicate [f] - (proxy [Ops$Predicate] [] - (op [x] (boolean (f x))))) - -(defn- binary-predicate [f] - (proxy [Ops$BinaryPredicate] [] - (op [x y] (boolean (f x y))))) - -(defn- int-and-object-predicate [f] - (proxy [Ops$IntAndObjectPredicate] [] - (op [i x] (boolean (f x i))))) - -(defn par - "Creates a parallel array from coll. ops, if supplied, perform - on-the-fly filtering or transformations during parallel realization - or calculation. ops form a chain, and bounds must precede filters, - must precede maps. ops must be a set of keyword value pairs of the - following forms: - - :bound [start end] - - Only elements from start (inclusive) to end (exclusive) will be - processed when the array is realized. - - :filter pred - - Filter preds remove elements from processing when the array is realized. pred - must be a function of one argument whose return will be processed - via boolean. - - :filter-index pred2 - - pred2 must be a function of two arguments, which will be an element - of the collection and the corresponding index, whose return will be - processed via boolean. - - :filter-with [pred2 coll2] - - pred2 must be a function of two arguments, which will be - corresponding elements of the 2 collections. - - :map f - - Map fns will be used to transform elements when the array is - realized. f must be a function of one argument. - - :map-index f2 - - f2 must be a function of two arguments, which will be an element of - the collection and the corresponding index. - - :map-with [f2 coll2] - - f2 must be a function of two arguments, which will be corresponding - elements of the 2 collections." - - ([coll] - (if (instance? ParallelArrayWithMapping coll) - coll - (. ParallelArray createUsingHandoff - (to-array coll) - (. ParallelArray defaultExecutor)))) - ([coll & ops] - (reduce (fn [pa [op args]] - (cond - (= op :bound) (. pa withBounds (args 0) (args 1)) - (= op :filter) (. pa withFilter (predicate args)) - (= op :filter-with) (. pa withFilter (binary-predicate (args 0)) (par (args 1))) - (= op :filter-index) (. pa withIndexedFilter (int-and-object-predicate args)) - (= op :map) (. pa withMapping (parallel/op args)) - (= op :map-with) (. pa withMapping (binary-op (args 0)) (par (args 1))) - (= op :map-index) (. pa withIndexedMapping (int-and-object-to-object args)) - :else (throw (Exception. (str "Unsupported par op: " op))))) - (par coll) - (partition 2 ops)))) - -;;;;;;;;;;;;;;;;;;;;; aggregate operations ;;;;;;;;;;;;;;;;;;;;;; -(defn pany - "Returns some (random) element of the coll if it satisfies the bound/filter/map" - [coll] - (. (par coll) any)) - -(defn pmax - "Returns the maximum element, presuming Comparable elements, unless - a Comparator comp is supplied" - ([coll] (. (par coll) max)) - ([coll comp] (. (par coll) max comp))) - -(defn pmin - "Returns the minimum element, presuming Comparable elements, unless - a Comparator comp is supplied" - ([coll] (. (par coll) min)) - ([coll comp] (. (par coll) min comp))) - -(defn- summary-map [s] - {:min (.min s) :max (.max s) :size (.size s) :min-index (.indexOfMin s) :max-index (.indexOfMax s)}) - -(defn psummary - "Returns a map of summary statistics (min. max, size, min-index, max-index, - presuming Comparable elements, unless a Comparator comp is supplied" - ([coll] (summary-map (. (par coll) summary))) - ([coll comp] (summary-map (. (par coll) summary comp)))) - -(defn preduce - "Returns the reduction of the realized elements of coll - using function f. Note f will not necessarily be called - consecutively, and so must be commutative. Also note that - (f base an-element) might be performed many times, i.e. base is not - an initial value as with sequential reduce." - [f base coll] - (. (par coll) (reduce (reducer f) base))) - -;;;;;;;;;;;;;;;;;;;;; collection-producing operations ;;;;;;;;;;;;;;;;;;;;;; - -(defn- pa-to-vec [pa] - (vec (. pa getArray))) - -(defn- pall - "Realizes a copy of the coll as a parallel array, with any bounds/filters/maps applied" - [coll] - (if (instance? ParallelArrayWithMapping coll) - (. coll all) - (par coll))) - -(defn pvec - "Returns the realized contents of the parallel array pa as a Clojure vector" - [pa] (pa-to-vec (pall pa))) - -(defn pdistinct - "Returns a parallel array of the distinct elements of coll" - [coll] - (pa-to-vec (. (pall coll) allUniqueElements))) - -;this doesn't work, passes null to reducer? -(defn- pcumulate [coll f init] - (.. (pall coll) (precumulate (reducer f) init))) - -(defn psort - "Returns a new vector consisting of the realized items in coll, sorted, - presuming Comparable elements, unless a Comparator comp is supplied" - ([coll] (pa-to-vec (. (pall coll) sort))) - ([coll comp] (pa-to-vec (. (pall coll) sort comp)))) - -(defn pfilter-nils - "Returns a vector containing the non-nil (realized) elements of coll" - [coll] - (pa-to-vec (. (pall coll) removeNulls))) - -(defn pfilter-dupes - "Returns a vector containing the (realized) elements of coll, - without any consecutive duplicates" - [coll] - (pa-to-vec (. (pall coll) removeConsecutiveDuplicates))) - - -(comment -(load-file "src/parallel.clj") -(refer 'parallel) -(pdistinct [1 2 3 2 1]) -;(pcumulate [1 2 3 2 1] + 0) ;broken, not exposed -(def a (make-array Object 1000000)) -(dotimes i (count a) - (aset a i (rand-int i))) -(time (reduce + 0 a)) -(time (preduce + 0 a)) -(time (count (distinct a))) -(time (count (pdistinct a))) - -(preduce + 0 [1 2 3 2 1]) -(preduce + 0 (psort a)) -(pvec (par [11 2 3 2] :filter-index (fn [x i] (> i x)))) -(pvec (par [11 2 3 2] :filter-with [(fn [x y] (> y x)) [110 2 33 2]])) - -(psummary ;or pvec/pmax etc - (par [11 2 3 2] - :filter-with [(fn [x y] (> y x)) - [110 2 33 2]] - :map #(* % 2))) - -(preduce + 0 - (par [11 2 3 2] - :filter-with [< [110 2 33 2]])) - -(time (reduce + 0 (map #(* % %) (range 1000000)))) -(time (preduce + 0 (par (range 1000000) :map-index *))) -(def v (range 1000000)) -(time (preduce + 0 (par v :map-index *))) -(time (preduce + 0 (par v :map #(* % %)))) -(time (reduce + 0 (map #(* % %) v))) -)
\ No newline at end of file diff --git a/src/proxy.clj b/src/proxy.clj deleted file mode 100644 index f72111a4..00000000 --- a/src/proxy.clj +++ /dev/null @@ -1,307 +0,0 @@ -; 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) - -(import - '(clojure.asm ClassWriter ClassVisitor Opcodes Type) - '(java.lang.reflect Modifier Constructor) - '(clojure.asm.commons Method GeneratorAdapter) - '(clojure.lang IProxy Reflector DynamicClassLoader IPersistentMap PersistentHashMap RT)) - -(def *proxy-classes* (ref {})) - -(defn method-sig [#^java.lang.reflect.Method meth] - [(. meth (getName)) (seq (. meth (getParameterTypes))) (. meth getReturnType)]) - -(defn get-proxy-class - "Takes an optional single class followed by zero or more - interfaces. If not supplied class defaults to Object. Creates an - returns an instance of a proxy class derived from the supplied - classes. The resulting value is cached and used for any subsequent - requests for the same class set. Returns a Class object." - [& bases] - (let [bases (if (. (first bases) (isInterface)) - (cons Object bases) - bases) - [super & interfaces] bases] - (or (get @*proxy-classes* bases) - (let [cv (new ClassWriter (. ClassWriter COMPUTE_MAXS)) - cname (str "clojure/lang/" (gensym "Proxy__")) - ctype (. Type (getObjectType cname)) - iname (fn [c] (.. Type (getType c) (getInternalName))) - fmap "__clojureFnMap" - totype (fn [c] (. Type (getType c))) - to-types (fn [cs] (if (pos? (count cs)) - (into-array (map totype cs)) - (make-array Type 0))) - super-type (totype super) - map-type (totype PersistentHashMap) - ifn-type (totype clojure.lang.IFn) - obj-type (totype Object) - sym-type (totype clojure.lang.Symbol) - rt-type (totype clojure.lang.RT) - ex-type (totype java.lang.UnsupportedOperationException) - gen-method - (fn [#^java.lang.reflect.Method meth else-gen] - (let [pclasses (. meth (getParameterTypes)) - ptypes (to-types pclasses) - rtype (totype (. meth (getReturnType))) - m (new Method (. meth (getName)) rtype ptypes) - gen (new GeneratorAdapter (. Opcodes ACC_PUBLIC) m nil nil cv) - else-label (. gen (newLabel)) - end-label (. gen (newLabel)) - decl-type (. Type (getType (. meth (getDeclaringClass))))] - (. gen (visitCode)) - (. gen (loadThis)) - (. gen (getField ctype fmap map-type)) - ;get symbol corresponding to name - (. gen (push (. meth (getName)))) - (. gen (invokeStatic sym-type (. Method (getMethod "clojure.lang.Symbol create(String)")))) - ;lookup fn in map - (. gen (invokeStatic rt-type (. Method (getMethod "Object get(Object, Object)")))) - (. gen (dup)) - (. gen (ifNull else-label)) - ;if found - (. gen (loadThis)) - ;box args - (dotimes i (count ptypes) - (. gen (loadArg i)) - (. clojure.lang.Compiler$HostExpr (emitBoxReturn nil gen (nth pclasses i)))) - ;call fn - (. gen (invokeInterface ifn-type (new Method "invoke" obj-type - (into-array (cons obj-type - (replicate (count ptypes) obj-type)))))) - ;unbox return - (. gen (unbox rtype)) - (when (= (. rtype (getSort)) (. Type VOID)) - (. gen (pop))) - (. gen (goTo end-label)) - - ;else call supplied alternative generator - (. gen (mark else-label)) - (. gen (pop)) - - (else-gen gen m) - - (. gen (mark end-label)) - (. gen (returnValue)) - (. gen (endMethod))))] - - ;start class definition - (. cv (visit (. Opcodes V1_5) (+ (. Opcodes ACC_PUBLIC) (. Opcodes ACC_SUPER)) - cname nil (iname super) - (into-array (map iname (cons IProxy interfaces))))) - ;add field for fn mappings - (. cv (visitField (+ (. Opcodes ACC_PRIVATE) (. Opcodes ACC_VOLATILE)) - fmap (. map-type (getDescriptor)) nil nil)) - ;add ctors matching/calling super's - (doseq #^Constructor ctor (. super (getDeclaredConstructors)) - (when-not (. Modifier (isPrivate (. ctor (getModifiers)))) - (let [ptypes (to-types (. ctor (getParameterTypes))) - m (new Method "<init>" (. Type VOID_TYPE) ptypes) - gen (new GeneratorAdapter (. Opcodes ACC_PUBLIC) m nil nil cv)] - (. gen (visitCode)) - ;call super ctor - (. gen (loadThis)) - (. gen (dup)) - (. gen (loadArgs)) - (. gen (invokeConstructor super-type m)) - ;init fmap - (. gen (getStatic map-type "EMPTY" map-type)) - (. gen (putField ctype fmap map-type)) - - (. gen (returnValue)) - (. gen (endMethod))))) - ;add IProxy methods - (let [m (. Method (getMethod "void __updateClojureFnMappings(clojure.lang.IPersistentMap)")) - gen (new GeneratorAdapter (. Opcodes ACC_PUBLIC) m nil nil cv)] - (. gen (visitCode)) - (. gen (loadThis)) - (. gen (dup)) - (. gen (getField ctype fmap map-type)) - (. gen (loadArgs)) - (. gen (invokeInterface (totype clojure.lang.IPersistentCollection) - (. Method (getMethod "clojure.lang.IPersistentCollection cons(Object)")))) - (. gen (checkCast map-type)) - (. gen (putField ctype fmap map-type)) - - (. gen (returnValue)) - (. gen (endMethod))) - (let [m (. Method (getMethod "clojure.lang.IPersistentMap __getClojureFnMappings()")) - gen (new GeneratorAdapter (. Opcodes ACC_PUBLIC) m nil nil cv)] - (. gen (visitCode)) - (. gen (loadThis)) - (. gen (getField ctype fmap map-type)) - (. gen (returnValue)) - (. gen (endMethod))) - - ;calc set of supers' non-private instance methods - (let [mm (loop [mm {} considered #{} c super] - (if c - (let [[mm considered] - (loop [mm mm - considered considered - meths (concat - (seq (. c (getDeclaredMethods))) - (seq (. c (getMethods))))] - (if meths - (let [#^java.lang.reflect.Method meth (first meths) - mods (. meth (getModifiers)) - mk (method-sig meth)] - (if (or (considered mk) - (. Modifier (isPrivate mods)) - (. Modifier (isStatic mods)) - (. Modifier (isFinal mods)) - (= "finalize" (.getName meth))) - (recur mm (conj considered mk) (rest meths)) - (recur (assoc mm mk meth) (conj considered mk) (rest meths)))) - [mm considered]))] - (recur mm considered (. c (getSuperclass)))) - mm))] - ;add methods matching supers', if no mapping -> call super - (doseq #^java.lang.reflect.Method meth (vals mm) - (gen-method meth - (fn [gen m] - (. gen (loadThis)) - ;push args - (. gen (loadArgs)) - ;call super - (. gen (visitMethodInsn (. Opcodes INVOKESPECIAL) - (. super-type (getInternalName)) - (. m (getName)) - (. m (getDescriptor))))))) - - ;add methods matching interfaces', if no mapping -> throw - (doseq #^Class iface interfaces - (doseq #^java.lang.reflect.Method meth (. iface (getMethods)) - (when-not (contains? mm (method-sig meth)) - (gen-method meth - (fn [gen m] - (. gen (throwException ex-type (. m (getName)))))))))) - - ;finish class def - (. cv (visitEnd)) - ;generate, cache and return class object - (let [loader (. RT ROOT_CLASSLOADER) - c (. loader (defineClass (. cname (replace "/" ".")) - (. cv (toByteArray))))] - (sync nil (commute *proxy-classes* assoc bases c)) - c))))) - -(defn construct-proxy - "Takes a proxy class and any arguments for its superclass ctor and - creates and returns an instance of the proxy." - [c & ctor-args] - (. Reflector (invokeConstructor c (to-array ctor-args)))) - -(defn update-proxy - "Takes a proxy instance and a map of symbols (whose names must - correspond to methods of the proxy superclass/superinterfaces) to - fns (which must take arguments matching the corresponding method, - plus an additional (explicit) first arg corresponding to this, and - updates (via assoc) the proxy's fn map. nil can be passed instead of - a fn, in which case the corresponding method will revert to the - default behavior. Note that this function can be used to update the - behavior of an existing instance without changing its identity." - [#^IProxy proxy mappings] - (. proxy (__updateClojureFnMappings mappings))) - -(defn proxy-mappings - "Takes a proxy instance and returns the proxy's fn map." - [#^IProxy proxy] - (. proxy (__getClojureFnMappings))) - -(defmacro proxy - "class-and-interfaces - a vector of class names - - args - a (possibly empty) vector of arguments to the superclass - constructor. - - f => (name [params*] body) or - (name ([params*] body) ([params+] body) ...) - - Expands to code which creates a instance of a proxy class that - implements the named class/interface(s) by calling the supplied - fns. A single class, if provided, must be first. If not provided it - defaults to Object. - - The interfaces names must be valid interface types. If a method fn - is not provided for a class method, the superclass methd will be - called. If a method fn is not provided for an interface method, an - UnsupportedOperationException will be thrown should it be - called. Method fns are closures and can capture the environment in - which proxy is called. Each method fn takes an additional implicit - first arg, which is bound to 'this. Note that while method fns can - be provided to override protected methods, they have no other access - to protected members, nor to super, as these capabilities cannot be - proxied." - [class-and-interfaces args & fs] - `(let [pc# (get-proxy-class ~@class-and-interfaces) - p# (construct-proxy pc# ~@args)] - (update-proxy p# - ~(loop [fmap {} fs fs] - (if fs - (let [[sym & meths] (first fs) - meths (if (vector? (first meths)) - (list meths) - meths) - meths (map (fn [[params & body]] - (cons (apply vector 'this params) body)) - meths)] - (recur (assoc fmap (list `quote (symbol (name sym))) (cons `fn meths)) (rest fs))) - fmap))) - p#)) - -(defn proxy-call-with-super [call this meth] - (let [m (proxy-mappings this)] - (update-proxy this (assoc m meth nil)) - (let [ret (call)] - (update-proxy this m) - ret))) - -(defmacro proxy-super - "Use to call a superclass method in the body of a proxy method. - Note, expansion captures 'this" - [meth & args] - `(proxy-call-with-super (fn [] (. ~'this ~meth ~@args)) ~'this '~(symbol (name meth)))) - -(defn bean - "Takes a Java object and returns a read-only implementation of the - map abstraction based upon its JavaBean properties." - [#^Object x] - (let [c (. x (getClass)) - pmap (reduce (fn [m #^java.beans.PropertyDescriptor pd] - (let [name (. pd (getName)) - method (. pd (getReadMethod))] - (if (and method (zero? (alength (. method (getParameterTypes))))) - (assoc m (keyword name) (fn [] (. method (invoke x nil)))) - m))) - {} - (seq (.. java.beans.Introspector - (getBeanInfo c) - (getPropertyDescriptors)))) - v (fn [k] ((pmap k))) - snapshot (fn [] - (reduce (fn [m e] - (assoc m (key e) ((val e)))) - {} (seq pmap)))] - (proxy [clojure.lang.APersistentMap] - [] - (containsKey [k] (contains? pmap k)) - (entryAt [k] (when (contains? pmap k) (new clojure.lang.MapEntry k (v k)))) - (valAt ([k] (v k)) - ([k default] (if (contains? pmap k) (v k) default))) - (cons [m] (conj (snapshot) m)) - (count [] (count pmap)) - (assoc [k v] (assoc (snapshot) k v)) - (without [k] (dissoc (snapshot) k)) - (seq [] ((fn thisfn [pseq] - (when pseq - (lazy-cons (new clojure.lang.MapEntry (first pseq) (v (first pseq))) - (thisfn (rest pseq))))) (keys pmap)))))) diff --git a/src/set.clj b/src/set.clj deleted file mode 100644 index e5e34cc0..00000000 --- a/src/set.clj +++ /dev/null @@ -1,116 +0,0 @@ -; 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 'set) -(clojure/refer 'clojure) - -(defn union - "Returns a set that is the union of the two sets." - [xset yset] - (reduce conj xset yset)) - -(defn difference - "Returns a set that is xset without the elements of yset." - [xset yset] - (reduce disj xset yset)) - -(defn intersection - "Returns a set of the elements present in both xset and yset." - [xset yset] - (difference xset (difference xset yset))) - -(defn select - "Returns a set of the elements for which pred is true" - [pred xset] - (reduce (fn [s k] (if (pred k) s (disj s k))) - xset xset)) - -(defn project - "Returns a rel of the elements of xrel with only the keys in ks" - [xrel ks] - (set (map #(select-keys % ks) xrel))) - -(defn rename-keys - "Returns the map with the keys in kmap renamed to the vals in kmap" - [map kmap] - (reduce - (fn [m [old new]] - (if (not= old new) - (-> m (assoc new (m old)) (dissoc old)) - m)) - map kmap)) - -(defn rename - "Returns a rel of the maps in xrel with the keys in kmap renamed to the vals in kmap" - [xrel kmap] - (set (map #(rename-keys % kmap) xrel))) - -(defn index - "Returns a map of the distinct values of ks in the xrel mapped to a - set of the maps in xrel with the corresponding values of ks." - [xrel ks] - (reduce - (fn [m x] - (let [ik (select-keys x ks)] - (assoc m ik (conj (get m ik #{}) x)))) - {} xrel)) - -(defn map-invert - "Returns the map with the vals mapped to the keys." - [m] (reduce (fn [m [k v]] (assoc m v k)) {} m)) - -(defn join - "When passed 2 rels, returns the rel corresponding to the natural - join. When passed an additional keymap, joins on the corresponding - keys." - ([xrel yrel] ;natural join - (if (and (seq xrel) (seq yrel)) - (let [ks (intersection (set (keys (first xrel))) (set (keys (first yrel)))) - [r s] (if (<= (count xrel) (count yrel)) - [xrel yrel] - [yrel xrel]) - idx (index r ks)] - (reduce (fn [ret x] - (let [found (idx (select-keys x ks))] - (if found - (reduce #(conj %1 (merge %2 x)) ret found) - ret))) - #{} s)) - #{})) - ([xrel yrel km] ;arbitrary key mapping - (let [[r s k] (if (<= (count xrel) (count yrel)) - [xrel yrel (map-invert km)] - [yrel xrel km]) - idx (index r (vals k))] - (reduce (fn [ret x] - (let [found (idx (rename-keys (select-keys x (keys k)) k))] - (if found - (reduce #(conj %1 (merge %2 x)) ret found) - ret))) - #{} s)))) - -(comment -(refer 'set) -(def xs #{{:a 11 :b 1 :c 1 :d 4} - {:a 2 :b 12 :c 2 :d 6} - {:a 3 :b 3 :c 3 :d 8 :f 42}}) - -(def ys #{{:a 11 :b 11 :c 11 :e 5} - {:a 12 :b 11 :c 12 :e 3} - {:a 3 :b 3 :c 3 :e 7 }}) - -(join xs ys) -(join xs (rename ys {:b :yb :c :yc}) {:a :a}) - -(union #{:a :b :c} #{:c :d :e }) -(difference #{:a :b :c} #{:c :d :e}) -(intersection #{:a :b :c} #{:c :d :e}) - -(index ys [:b]) -) - diff --git a/src/xml.clj b/src/xml.clj deleted file mode 100644 index 7ad8198c..00000000 --- a/src/xml.clj +++ /dev/null @@ -1,117 +0,0 @@ -; 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 'xml) -(clojure/refer 'clojure) - -(import '(org.xml.sax ContentHandler Attributes SAXException) - '(javax.xml.parsers SAXParser SAXParserFactory)) - -(def *stack*) -(def *current*) -(def *state*) ; :element :chars :between -(def *sb*) - -(defstruct element :tag :attrs :content) - -(def tag (accessor element :tag)) -(def attrs (accessor element :attrs)) -(def content (accessor element :content)) - -(def content-handler - (let [push-content (fn [e c] - (assoc e :content (conj (or (:content e) []) c))) - push-chars (fn [] - (when (and (= *state* :chars) - (some (complement #(. Character (isWhitespace %))) (str *sb*))) - (set! *current* (push-content *current* (str *sb*)))))] - (new clojure.lang.XMLHandler - (proxy [ContentHandler] [] - (startElement [uri local-name q-name #^Attributes atts] - (let [attrs (fn [ret i] - (if (neg? i) - ret - (recur (assoc ret - (. clojure.lang.Keyword (intern (symbol (. atts (getQName i))))) - (. atts (getValue i))) - (dec i)))) - e (struct element - (. clojure.lang.Keyword (intern (symbol q-name))) - (when (pos? (. atts (getLength))) - (attrs {} (dec (. atts (getLength))))))] - (push-chars) - (set! *stack* (conj *stack* *current*)) - (set! *current* e) - (set! *state* :element)) - nil) - (endElement [uri local-name q-name] - (push-chars) - (set! *current* (push-content (peek *stack*) *current*)) - (set! *stack* (pop *stack*)) - (set! *state* :between) - nil) - (characters [ch start length] - (when-not (= *state* :chars) - (set! *sb* (new StringBuilder))) - (let [#^StringBuilder sb *sb*] - (. sb (append ch start length)) - (set! *state* :chars)) - nil) - (setDocumentLocator [locator]) - (startDocument []) - (endDocument []) - (startPrefixMapping [prefix uri]) - (endPrefixMapping [prefix]) - (ignorableWhitespace [ch start length]) - (processingInstruction [target data]) - (skippedEntity [name]) - )))) - -(defn startparse-sax [s ch] - (.. SAXParserFactory (newInstance) (newSAXParser) (parse s ch))) - -(defn parse - "Parses and loads the source s, which can be a File, InputStream or - String naming a URI. Returns a tree of the xml/element struct-map, - which has the keys :tag, :attrs, and :content. and accessor fns tag, - attrs, and content. Other parsers can be supplied by passing - startparse, a fn taking a source and a ContentHandler and returning - a parser" - ([s] (parse s startparse-sax)) - ([s startparse] - (binding [*stack* nil - *current* (struct element) - *state* :between - *sb* nil] - (startparse s content-handler) - ((:content *current*) 0)))) - -(defn emit-element [e] - (if (instance? String e) - (println e) - (do - (print (str "<" (name (:tag e)))) - (when (:attrs e) - (doseq attr (:attrs e) - (print (str " " (name (key attr)) "='" (val attr)"'")))) - (if (:content e) - (do - (println ">") - (doseq c (:content e) - (emit-element c)) - (println (str "</" (name (:tag e)) ">"))) - (println "/>"))))) - -(defn emit [x] - (println "<?xml version='1.0' encoding='UTF-8'?>") - (emit-element x)) - -;(export '(tag attrs content parse element emit emit-element)) - -;(load-file "/Users/rich/dev/clojure/src/xml.clj") -;(def x (xml/parse "http://arstechnica.com/journals.rssx")) diff --git a/src/zip.clj b/src/zip.clj deleted file mode 100644 index e6794e73..00000000 --- a/src/zip.clj +++ /dev/null @@ -1,248 +0,0 @@ -; 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. - -;functional hierarchical zipper, with navigation, editing and enumeration -;see Huet - -(in-ns 'zip) -(clojure/refer 'clojure :exclude '(replace)) - -(defn zipper - "Creates a new zipper structure. - - branch? is a fn that, given a node, returns true if can have - children, even if it currently doesn't. - - children is a fn that, given a branch node, returns a seq of its - children. - - make-node is a fn that, given an existing node and a seq of - children, returns a new branch node with the supplied children. - root is the root node." - [branch? children make-node root] - #^{:zip/branch? branch? :zip/children children :zip/make-node make-node} - [root nil]) - -(defn seq-zip - "Returns a zipper for nested sequences, given a root sequence" - [root] - (zipper seq? identity (fn [node children] children) root)) - -(defn vector-zip - "Returns a zipper for nested vectors, given a root vector" - [root] - (zipper vector? seq (fn [node children] (apply vector children)) root)) - -(defn xml-zip - "Returns a zipper for xml elements (as from xml/parse), - given a root element" - [root] - (zipper (complement string?) - (comp seq :content) - (fn [node children] - (assoc node :content (and children (apply vector children)))) - root)) - -(defn node - "Returns the node at loc" - [loc] (loc 0)) - -(defn branch? - "Returns true if the node at loc is a branch" - [loc] - ((:zip/branch? ^loc) (node loc))) - -(defn children - "Returns a seq of the children of node at loc, which must be a branch" - [loc] - ((:zip/children ^loc) (node loc))) - -(defn make-node - "Returns a new branch node, given an existing node and new - children. The loc is only used to supply the constructor." - [loc node children] - ((:zip/make-node ^loc) node children)) - -(defn path - "Returns a seq of nodes leading to this loc" - [loc] - (:pnodes (loc 1))) - -(defn lefts - "Returns a seq of the left siblings of this loc" - [loc] - (seq (:l (loc 1)))) - -(defn rights - "Returns a seq of the right siblings of this loc" - [loc] - (:r (loc 1))) - - -(defn down - "Returns the loc of the leftmost child of the node at this loc, or - nil if no children" - [loc] - (let [[node path] loc - [c & crest :as cs] (children loc)] - (when cs - (with-meta [c {:l [] - :pnodes (if path (conj (:pnodes path) node) [node]) - :ppath path - :r crest}] ^loc)))) - -(defn up - "Returns the loc of the parent of the node at this loc, or nil if at - the top" - [loc] - (let [[node {l :l, ppath :ppath, pnodes :pnodes r :r, changed? :changed?, :as path}] loc] - (when path - (let [pnode (peek pnodes)] - (with-meta (if changed? - [(make-node loc pnode (concat l (cons node r))) - (and ppath (assoc ppath :changed? true))] - [pnode ppath]) - ^loc))))) - -(defn root - "zips all the way up and returns the root node, reflecting any - changes." - [loc] - (if (= :end (loc 1)) - (node loc) - (let [p (up loc)] - (if p - (recur p) - (node loc))))) - -(defn right - "Returns the loc of the right sibling of the node at this loc, or nil" - [loc] - (let [[node {l :l [r & rrest :as rs] :r :as path}] loc] - (when (and path rs) - (with-meta [r (assoc path :l (conj l node) :r rrest)] ^loc)))) - -(defn left - "Returns the loc of the left sibling of the node at this loc, or nil" - [loc] - (let [[node {l :l r :r :as path}] loc] - (when (and path (seq l)) - (with-meta [(peek l) (assoc path :l (pop l) :r (cons node r))] ^loc)))) - -(defn insert-left - "Inserts the item as the left sibling of the node at this loc, - without moving" - [loc item] - (let [[node {l :l :as path}] loc] - (if (nil? path) - (throw (new Exception "Insert at top")) - (with-meta [node (assoc path :l (conj l item) :changed? true)] ^loc)))) - -(defn insert-right - "Inserts the item as the right sibling of the node at this loc, - without moving" - [loc item] - (let [[node {r :r :as path}] loc] - (if (nil? path) - (throw (new Exception "Insert at top")) - (with-meta [node (assoc path :r (cons item r) :changed? true)] ^loc)))) - -(defn replace - "Replaces the node at this loc, without moving" - [loc node] - (let [[_ path] loc] - (with-meta [node (assoc path :changed? true)] ^loc))) - -(defn edit - "Replaces the node at this loc with the value of (f node args)" - [loc f & args] - (replace loc (apply f (node loc) args))) - -(defn insert-child - "Inserts the item as the leftmost child of the node at this loc, - without moving" - [loc item] - (replace loc (make-node loc (node loc) (cons item (children loc))))) - -(defn append-child - "Inserts the item as the rightmost child of the node at this loc, - without moving" - [loc item] - (replace loc (make-node loc (node loc) (concat (children loc) [item])))) - -(defn next - "Moves to the next loc in the hierarchy, depth-first. When reaching - the end, returns a distinguished loc detectable via end?. If already - at the end, stays there." - [loc] - (if (= :end (loc 1)) - loc - (or - (and (branch? loc) (down loc)) - (right loc) - (loop [p loc] - (if (up p) - (or (right (up p)) (recur (up p))) - [(node p) :end]))))) - -(defn end? - "Returns true if loc represents the end of a depth-first walk" - [loc] - (= :end (loc 1))) - -(defn remove - "Removes the node at loc, returning the loc that would have preceded - it in a depth-first walk." - [loc] - (let [[node {l :l, ppath :ppath, pnodes :pnodes, rs :r, :as path}] loc] - (if (nil? path) - (throw (new Exception "Remove at top")) - (if (pos? (count l)) - (with-meta [(peek l) (assoc path :l (pop l) :changed? true)] ^loc) - (with-meta [(make-node loc (peek pnodes) rs) - (and ppath (assoc ppath :changed? true))] - ^loc))))) - -(comment - -(load-file "/Users/rich/dev/clojure/src/zip.clj") -(refer 'zip) -(def data '[[a * b] + [c * d]]) -(def dz (vector-zip data)) - -(right (down (right (right (down dz))))) -(lefts (right (down (right (right (down dz)))))) -(rights (right (down (right (right (down dz)))))) -(up (up (right (down (right (right (down dz))))))) -(path (right (down (right (right (down dz)))))) - -(-> dz down right right down right) -(-> dz down right right down right (replace '/) root) -(-> dz next next (edit str) next next next (replace '/) root) -(-> dz next next next next next next next next next remove root) -(-> dz next next next next next next next next next remove (insert-right 'e) root) -(-> dz next next next next next next next next next remove up (append-child 'e) root) - -(end? (-> dz next next next next next next next next next remove next)) - -(-> dz next remove next remove root) - -(loop [loc dz] - (if (end? loc) - (root loc) - (recur (next (if (= '* (node loc)) - (replace loc '/) - loc))))) - -(loop [loc dz] - (if (end? loc) - (root loc) - (recur (next (if (= '* (node loc)) - (remove loc) - loc))))) -) |