summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2009-10-22 18:33:32 -0400
committerRich Hickey <richhickey@gmail.com>2009-10-22 18:33:32 -0400
commitc0218cfc80ba9ae4c1808e8f5644e14c464a5268 (patch)
treec12187f5abc452c9aa64338cbb31663f8bea12d5
parent3d69750b26d41d72920264ce8d338c20be7383a9 (diff)
parentd910b3d997e1c40528aab2212fe356a8598bb738 (diff)
Merge branch 'master' into new
-rw-r--r--build.xml8
-rw-r--r--src/clj/clojure/core.clj478
-rw-r--r--src/clj/clojure/core_proxy.clj13
-rw-r--r--src/clj/clojure/main.clj6
-rw-r--r--src/clj/clojure/test.clj2
-rw-r--r--src/clj/clojure/test/tap.clj2
-rw-r--r--src/clj/clojure/xml.clj18
-rw-r--r--src/clj/clojure/zip.clj10
-rw-r--r--src/jvm/clojure/lang/ATransientMap.java86
-rw-r--r--src/jvm/clojure/lang/ATransientSet.java54
-rw-r--r--src/jvm/clojure/lang/ArraySeq.java376
-rw-r--r--src/jvm/clojure/lang/Associative.java5
-rw-r--r--src/jvm/clojure/lang/Compiler.java36
-rw-r--r--src/jvm/clojure/lang/IEditableCollection.java17
-rw-r--r--src/jvm/clojure/lang/ILookup.java19
-rw-r--r--src/jvm/clojure/lang/ITransientAssociative.java18
-rw-r--r--src/jvm/clojure/lang/ITransientCollection.java20
-rw-r--r--src/jvm/clojure/lang/ITransientMap.java22
-rw-r--r--src/jvm/clojure/lang/ITransientSet.java19
-rw-r--r--src/jvm/clojure/lang/ITransientVector.java20
-rw-r--r--src/jvm/clojure/lang/Keyword.java12
-rw-r--r--src/jvm/clojure/lang/LazilyPersistentVector.java136
-rw-r--r--src/jvm/clojure/lang/LispReader.java15
-rw-r--r--src/jvm/clojure/lang/LockingTransaction.java129
-rw-r--r--src/jvm/clojure/lang/Numbers.java8
-rw-r--r--src/jvm/clojure/lang/PersistentArrayMap.java609
-rw-r--r--src/jvm/clojure/lang/PersistentHashMap.java1100
-rw-r--r--src/jvm/clojure/lang/PersistentHashSet.java16
-rw-r--r--src/jvm/clojure/lang/PersistentVector.java571
-rw-r--r--src/jvm/clojure/lang/RT.java25
-rw-r--r--src/jvm/clojure/lang/Ref.java2
-rw-r--r--src/jvm/clojure/lang/StringSeq.java4
-rw-r--r--src/jvm/clojure/lang/Symbol.java2
-rw-r--r--test/clojure/test_clojure.clj20
-rw-r--r--test/clojure/test_clojure/compilation.clj6
-rw-r--r--test/clojure/test_clojure/control.clj169
-rw-r--r--test/clojure/test_clojure/for.clj5
-rw-r--r--test/clojure/test_clojure/java_interop.clj4
-rw-r--r--test/clojure/test_clojure/numbers.clj49
-rw-r--r--test/clojure/test_clojure/predicates.clj2
-rw-r--r--test/clojure/test_clojure/reader.clj15
-rw-r--r--test/clojure/test_clojure/sequences.clj42
-rw-r--r--test/clojure/test_clojure/test.clj6
-rw-r--r--test/clojure/test_clojure/test_fixtures.clj2
-rw-r--r--test/clojure/test_clojure/vars.clj4
45 files changed, 3028 insertions, 1154 deletions
diff --git a/build.xml b/build.xml
index b37adefc..482e9724 100644
--- a/build.xml
+++ b/build.xml
@@ -85,8 +85,10 @@
<target name="compile-clojure" depends="compile-java"
description="Compile Clojure sources.">
<java classname="clojure.lang.Compile"
- classpath="${build}:${cljsrc}">
+ classpath="${build}:${cljsrc}"
+ failonerror="true">
<sysproperty key="clojure.compile.path" value="${build}"/>
+ <!-- <sysproperty key="clojure.compile.warn-on-reflection" value="true"/> -->
<arg value="clojure.core"/>
<arg value="clojure.main"/>
<arg value="clojure.set"/>
@@ -119,13 +121,13 @@
<target name="test"
description="Run clojure tests">
<!-- depends="clojure"> -->
- <java classname="clojure.main">
+ <java classname="clojure.main" failonerror="true">
<classpath>
<path location="${test}"/>
<path location="${clojure_jar}"/>
</classpath>
<arg value="-e"/>
- <arg value="(require '(clojure [test-clojure :as main])) (main/run)"/>
+ <arg value="(require '(clojure [test-clojure :as main])) (main/run-ant)"/>
</java>
</target>
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 3b2ed7b1..c4ab4785 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -251,7 +251,9 @@
(defn vec
"Creates a new vector containing the contents of coll."
([coll]
- (. clojure.lang.LazilyPersistentVector (createOwning (to-array coll)))))
+ (if (instance? java.util.Collection coll)
+ (clojure.lang.LazilyPersistentVector/create coll)
+ (. clojure.lang.LazilyPersistentVector (createOwning (to-array coll))))))
(defn hash-map
"keyval => key val
@@ -355,14 +357,16 @@
(defn symbol
"Returns a Symbol with the given namespace and name."
- ([name] (if (symbol? name) name (. clojure.lang.Symbol (intern name))))
- ([ns name] (. clojure.lang.Symbol (intern ns name))))
+ {:tag clojure.lang.Symbol}
+ ([name] (if (symbol? 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] (if (keyword? name) name (. clojure.lang.Keyword (intern nil name))))
- ([ns name] (. clojure.lang.Keyword (intern ns name))))
+ {:tag clojure.lang.Keyword}
+ ([name] (if (keyword? name) name (clojure.lang.Keyword/intern name)))
+ ([ns name] (clojure.lang.Keyword/intern ns name)))
(defn gensym
"Returns a new symbol with a unique name. If a prefix string is
@@ -393,11 +397,29 @@
(nil? (next arglist)) (seq (first arglist))
:else (cons (first arglist) (spread (next arglist)))))
+(defn list*
+ "Creates a new list containing the items prepended to the rest, the
+ last of which will be treated as a sequence."
+ ([args] (seq args))
+ ([a args] (cons a args))
+ ([a b args] (cons a (cons b args)))
+ ([a b c args] (cons a (cons b (cons c args))))
+ ([a b c d & more]
+ (cons a (cons b (cons c (cons d (spread more)))))))
+
(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))))
+ ([#^clojure.lang.IFn f args]
+ (. f (applyTo (seq args))))
+ ([#^clojure.lang.IFn f x args]
+ (. f (applyTo (list* x args))))
+ ([#^clojure.lang.IFn f x y args]
+ (. f (applyTo (list* x y args))))
+ ([#^clojure.lang.IFn f x y z args]
+ (. f (applyTo (list* x y z args))))
+ ([#^clojure.lang.IFn f a b c d & args]
+ (. f (applyTo (cons a (cons b (cons c (cons d (spread args)))))))))
(defn vary-meta
"Returns an object of the same type and value as obj, with
@@ -405,10 +427,7 @@
[obj f & args]
(with-meta obj (apply f (meta obj) args)))
-(defn list*
- "Creates a new list containing the item prepended to more."
- [item & more]
- (spread (cons item more)))
+
(defmacro lazy-seq
"Takes a body of expressions that returns an ISeq or nil, and yields
@@ -418,25 +437,56 @@
[& body]
(list 'new 'clojure.lang.LazySeq (list* '#^{:once true} fn* [] body)))
+(defn #^clojure.lang.ChunkBuffer chunk-buffer [capacity]
+ (clojure.lang.ChunkBuffer. capacity))
+
+(defn chunk-append [#^clojure.lang.ChunkBuffer b x]
+ (.add b x))
+
+(defn chunk [#^clojure.lang.ChunkBuffer b]
+ (.chunk b))
+
+(defn #^clojure.lang.IChunk chunk-first [#^clojure.lang.IChunkedSeq s]
+ (.chunkedFirst s))
+
+(defn #^clojure.lang.ISeq chunk-rest [#^clojure.lang.IChunkedSeq s]
+ (.chunkedMore s))
+
+(defn #^clojure.lang.ISeq chunk-next [#^clojure.lang.IChunkedSeq s]
+ (.chunkedNext s))
+
+(defn chunk-cons [chunk rest]
+ (if (clojure.lang.Numbers/isZero (clojure.lang.RT/count chunk))
+ rest
+ (clojure.lang.ChunkedCons. chunk rest)))
+
+(defn chunked-seq? [s]
+ (instance? clojure.lang.IChunkedSeq s))
+
(defn concat
"Returns a lazy seq representing the concatenation of the elements in the supplied colls."
([] (lazy-seq nil))
([x] (lazy-seq x))
([x y]
- (lazy-seq
+ (lazy-seq
(let [s (seq x)]
(if s
- (cons (first s) (concat (rest s) y))
+ (if (chunked-seq? s)
+ (chunk-cons (chunk-first s) (concat (chunk-rest s) y))
+ (cons (first s) (concat (rest s) y)))
y))))
([x y & zs]
(let [cat (fn cat [xys zs]
(lazy-seq
- (let [xys (seq xys)]
- (if xys
- (cons (first xys) (cat (rest xys) zs))
- (when zs
- (cat (first zs) (next zs)))))))]
- (cat (concat x y) zs))))
+ (let [xys (seq xys)]
+ (if xys
+ (if (chunked-seq? xys)
+ (chunk-cons (chunk-first xys)
+ (cat (chunk-rest xys) zs))
+ (cons (first xys) (cat (rest xys) zs)))
+ (when zs
+ (cat (first zs) (next zs)))))))]
+ (cat (concat x y) zs))))
;;;;;;;;;;;;;;;;at this point all the support for syntax-quote exists;;;;;;;;;;;;;;;;;;;;;;
@@ -492,10 +542,11 @@
(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 and collections in a type-independent
- manner. x must implement Comparable"
+ "Comparator. Returns a negative number, zero, or a positive number
+ when x is logically 'less than', 'equal to', or 'greater than'
+ y. Same as Java x.compareTo(y) except it also works for nil, and
+ compares numbers and collections 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)))
@@ -545,8 +596,8 @@
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."
- {:inline (fn [c i] `(. clojure.lang.RT (nth ~c ~i)))
- :inline-arities #{2}}
+ {:inline (fn [c i & nf] `(. clojure.lang.RT (nth ~c ~i ~@nf)))
+ :inline-arities #{2 3}}
([coll index] (. clojure.lang.RT (nth coll index)))
([coll index not-found] (. clojure.lang.RT (nth coll index not-found))))
@@ -569,32 +620,6 @@
{:inline (fn [x] `(. clojure.lang.Numbers (inc ~x)))}
[x] (. clojure.lang.Numbers (inc x)))
-(defn #^clojure.lang.ChunkBuffer chunk-buffer [capacity]
- (clojure.lang.ChunkBuffer. capacity))
-
-(defn chunk-append [#^clojure.lang.ChunkBuffer b x]
- (.add b x))
-
-(defn chunk [#^clojure.lang.ChunkBuffer b]
- (.chunk b))
-
-(defn #^clojure.lang.IChunk chunk-first [#^clojure.lang.IChunkedSeq s]
- (.chunkedFirst s))
-
-(defn #^clojure.lang.ISeq chunk-rest [#^clojure.lang.IChunkedSeq s]
- (.chunkedMore s))
-
-(defn #^clojure.lang.ISeq chunk-next [#^clojure.lang.IChunkedSeq s]
- (.chunkedNext s))
-
-(defn chunk-cons [chunk rest]
- (if (zero? (count chunk))
- rest
- (clojure.lang.ChunkedCons. chunk rest)))
-
-(defn chunked-seq? [s]
- (instance? clojure.lang.IChunkedSeq s))
-
(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
@@ -1048,6 +1073,16 @@
(list form x)))
([x form & more] `(-> (-> ~x ~form) ~@more)))
+(defmacro ->>
+ "Threads the expr through the forms. Inserts x as the
+ last 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
+ last item in second form, etc."
+ ([x form] (if (seq? form)
+ `(~(first form) ~@(next form) ~x)
+ (list form x)))
+ ([x form & more] `(->> (->> ~x ~form) ~@more)))
+
;;multimethods
(def global-hierarchy)
@@ -1159,28 +1194,58 @@
(let [~form temp#]
~@body)))))
+(defn push-thread-bindings
+ "WARNING: This is a low-level function. Prefer high-level macros like
+ binding where ever possible.
+
+ Takes a map of Var/value pairs. Binds each Var to the associated value for
+ the current thread. Each call *MUST* be accompanied by a matching call to
+ pop-thread-bindings wrapped in a try-finally!
+
+ (push-thread-bindings bindings)
+ (try
+ ...
+ (finally
+ (pop-thread-bindings)))"
+ [bindings]
+ (clojure.lang.Var/pushThreadBindings bindings))
+
+(defn pop-thread-bindings
+ "Pop one set of bindings pushed with push-binding before. It is an error to
+ pop bindings without pushing before."
+ []
+ (clojure.lang.Var/popThreadBindings))
+
+(defn get-thread-bindings
+ "Get a map with the Var/value pairs which is currently in effect for the
+ current thread."
+ []
+ (clojure.lang.Var/getThreadBindings))
+
(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."
+ re-establishes the bindings that existed before. The new bindings
+ are made in parallel (unlike let); all init-exprs are evaluated
+ before the vars are bound to their new values."
[bindings & body]
- (assert-args binding
- (vector? bindings) "a vector for its binding"
- (even? (count bindings)) "an even number of forms in binding vector")
- (let [var-ize (fn [var-vals]
- (loop [ret [] vvs (seq var-vals)]
- (if vvs
- (recur (conj (conj ret `(var ~(first vvs))) (second vvs))
- (next (next vvs)))
- (seq ret))))]
- `(let []
- (. clojure.lang.Var (pushThreadBindings (hash-map ~@(var-ize bindings))))
- (try
- ~@body
- (finally
- (. clojure.lang.Var (popThreadBindings)))))))
+ (assert-args binding
+ (vector? bindings) "a vector for its binding"
+ (even? (count bindings)) "an even number of forms in binding vector")
+ (let [var-ize (fn [var-vals]
+ (loop [ret [] vvs (seq var-vals)]
+ (if vvs
+ (recur (conj (conj ret `(var ~(first vvs))) (second vvs))
+ (next (next vvs)))
+ (seq ret))))]
+ `(let []
+ (push-thread-bindings (hash-map ~@(var-ize bindings)))
+ (try
+ ~@body
+ (finally
+ (pop-thread-bindings))))))
(defn find-var
"Returns the global var named by the namespace-qualified symbol, or
@@ -1501,13 +1566,65 @@
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)]
+ ([f] f)
+ ([f g]
+ (fn
+ ([] (f (g)))
+ ([x] (f (g x)))
+ ([x y] (f (g x y)))
+ ([x y z] (f (g x y z)))
+ ([x y z & args] (f (apply g x y z args)))))
+ ([f g h]
+ (fn
+ ([] (f (g (h))))
+ ([x] (f (g (h x))))
+ ([x y] (f (g (h x y))))
+ ([x y z] (f (g (h x y z))))
+ ([x y z & args] (f (g (apply h x y z args))))))
+ ([f1 f2 f3 & fs]
+ (let [fs (reverse (list* f1 f2 f3 fs))]
(fn [& args]
(loop [ret (apply (first fs) args) fs (next fs)]
(if fs
(recur ((first fs) ret) (next fs))
- ret)))))
+ ret))))))
+
+(defn juxt
+ "Alpha - name subject to change.
+ Takes a set of functions and returns a fn that is the juxtaposition
+ of those fns. The returned fn takes a variable number of args, and
+ returns a vector containing the result of applying each fn to the
+ args (left-to-right).
+ ((juxt a b c) x) => [(a x) (b x) (c x)]"
+ ([f]
+ (fn
+ ([] [(f)])
+ ([x] [(f x)])
+ ([x y] [(f x y)])
+ ([x y z] [(f x y z)])
+ ([x y z & args] [(apply f x y z args)])))
+ ([f g]
+ (fn
+ ([] [(f) (g)])
+ ([x] [(f x) (g x)])
+ ([x y] [(f x y) (g x y)])
+ ([x y z] [(f x y z) (g x y z)])
+ ([x y z & args] [(apply f x y z args) (apply g x y z args)])))
+ ([f g h]
+ (fn
+ ([] [(f) (g) (h)])
+ ([x] [(f x) (g x) (h x)])
+ ([x y] [(f x y) (g x y) (h x y)])
+ ([x y z] [(f x y z) (g x y z) (h x y z)])
+ ([x y z & args] [(apply f x y z args) (apply g x y z args) (apply h x y z args)])))
+ ([f g h & fs]
+ (let [fs (list* f g h fs)]
+ (fn
+ ([] (reduce #(conj %1 (%2)) [] fs))
+ ([x] (reduce #(conj %1 (%2 x)) [] fs))
+ ([x y] (reduce #(conj %1 (%2 x y)) [] fs))
+ ([x y z] (reduce #(conj %1 (%2 x y z)) [] fs))
+ ([x y z & args] (reduce #(conj %1 (apply %2 x y z args)) [] fs))))))
(defn partial
"Takes a function f and fewer than the normal arguments to f, and
@@ -1685,6 +1802,15 @@
([s] (drop-last 1 s))
([n s] (map (fn [x _] x) s (drop n s))))
+(defn take-last
+ "Returns a seq of the last n items in coll. Depending on the type
+ of coll may be no better than linear time. For vectors, see also subvec."
+ [n coll]
+ (loop [s (seq coll), lead (seq (drop n coll))]
+ (if lead
+ (recur (next s) (next lead))
+ s)))
+
(defn drop-while
"Returns a lazy sequence of the items in coll starting from the first
item for which (pred item) returns nil."
@@ -1860,27 +1986,49 @@
(if-not exprs
[true `(do ~@body)]
(let [k (first exprs)
- v (second exprs)
- seqsym (when-not (keyword? k) (gensym))
- recform (if (keyword? k) recform `(recur (next ~seqsym)))
- steppair (step recform (nnext exprs))
- needrec (steppair 0)
- subform (steppair 1)]
- (cond
- (= k :let) [needrec `(let ~v ~subform)]
- (= k :while) [false `(when ~v
- ~subform
- ~@(when needrec [recform]))]
- (= k :when) [false `(if ~v
- (do
- ~subform
- ~@(when needrec [recform]))
- ~recform)]
- :else [true `(loop [~seqsym (seq ~v)]
- (when ~seqsym
- (let [~k (first ~seqsym)]
- ~subform
- ~@(when needrec [recform]))))]))))]
+ v (second exprs)]
+ (if (keyword? k)
+ (let [steppair (step recform (nnext exprs))
+ needrec (steppair 0)
+ subform (steppair 1)]
+ (cond
+ (= k :let) [needrec `(let ~v ~subform)]
+ (= k :while) [false `(when ~v
+ ~subform
+ ~@(when needrec [recform]))]
+ (= k :when) [false `(if ~v
+ (do
+ ~subform
+ ~@(when needrec [recform]))
+ ~recform)]))
+ (let [seq- (gensym "seq_")
+ chunk- (with-meta (gensym "chunk_")
+ {:tag 'clojure.lang.IChunk})
+ count- (gensym "count_")
+ i- (gensym "i_")
+ recform `(recur (next ~seq-) nil (int 0) (int 0))
+ steppair (step recform (nnext exprs))
+ needrec (steppair 0)
+ subform (steppair 1)
+ recform-chunk
+ `(recur ~seq- ~chunk- ~count- (unchecked-inc ~i-))
+ steppair-chunk (step recform-chunk (nnext exprs))
+ subform-chunk (steppair-chunk 1)]
+ [true
+ `(loop [~seq- (seq ~v), ~chunk- nil,
+ ~count- (int 0), ~i- (int 0)]
+ (if (< ~i- ~count-)
+ (let [~k (.nth ~chunk- ~i-)]
+ ~subform-chunk
+ ~@(when needrec [recform-chunk]))
+ (when-let [~seq- (seq ~seq-)]
+ (if (chunked-seq? ~seq-)
+ (let [c# (chunk-first ~seq-)]
+ (recur (chunk-rest ~seq-) c#
+ (int (count c#)) (int 0)))
+ (let [~k (first ~seq-)]
+ ~subform
+ ~@(when needrec [recform]))))))])))))]
(nth (step nil (seq seq-exprs)) 1)))
(defn dorun
@@ -2586,10 +2734,18 @@
(cons (first s) (take-nth n (drop n s))))))
(defn interleave
- "Returns a lazy seq of the first item in each coll, then the second
- etc."
- [& colls]
- (apply concat (apply map list colls)))
+ "Returns a lazy seq of the first item in each coll, then the second etc."
+ ([c1 c2]
+ (lazy-seq
+ (let [s1 (seq c1) s2 (seq c2)]
+ (when (and s1 s2)
+ (cons (first s1) (cons (first s2)
+ (interleave (rest s1) (rest s2))))))))
+ ([c1 c2 & colls]
+ (lazy-seq
+ (let [ss (map seq (conj colls c2 c1))]
+ (when (every? identity ss)
+ (concat (map first ss) (apply interleave (map rest ss))))))))
(defn var-get
"Gets the value in the var object"
@@ -2821,7 +2977,7 @@
binding-forms. Supported modifiers are: :let [binding-form expr ...],
:while test, :when test.
- (take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))"
+ (take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))"
[seq-exprs body-expr]
(assert-args for
(vector? seq-exprs) "a vector for its binding"
@@ -2832,7 +2988,7 @@
(conj (pop groups) (conj (peek groups) [k v]))
(conj groups [k v])))
[] (partition 2 seq-exprs)))
- err (fn [& msg] (throw (IllegalArgumentException. (apply str msg))))
+ err (fn [& msg] (throw (IllegalArgumentException. #^String (apply str msg))))
emit-bind (fn emit-bind [[[bind expr & mod-pairs]
& [[_ next-expr] :as next-groups]]]
(let [giter (gensym "iter__")
@@ -2853,11 +3009,48 @@
(recur (rest ~gxs))))
:else `(cons ~body-expr
(~giter (rest ~gxs)))))]
- `(fn ~giter [~gxs]
- (lazy-seq
- (loop [~gxs ~gxs]
- (when-first [~bind ~gxs]
- ~(do-mod mod-pairs)))))))]
+ (if next-groups
+ #_"not the inner-most loop"
+ `(fn ~giter [~gxs]
+ (lazy-seq
+ (loop [~gxs ~gxs]
+ (when-first [~bind ~gxs]
+ ~(do-mod mod-pairs)))))
+ #_"inner-most loop"
+ (let [gi (gensym "i__")
+ gb (gensym "b__")
+ do-cmod (fn do-cmod [[[k v :as pair] & etc]]
+ (cond
+ (= k :let) `(let ~v ~(do-cmod etc))
+ (= k :while) `(when ~v ~(do-cmod etc))
+ (= k :when) `(if ~v
+ ~(do-cmod etc)
+ (recur
+ (unchecked-inc ~gi)))
+ (keyword? k)
+ (err "Invalid 'for' keyword " k)
+ :else
+ `(do (chunk-append ~gb ~body-expr)
+ (recur (unchecked-inc ~gi)))))]
+ `(fn ~giter [~gxs]
+ (lazy-seq
+ (loop [~gxs ~gxs]
+ (when-let [~gxs (seq ~gxs)]
+ (if (chunked-seq? ~gxs)
+ (let [c# (chunk-first ~gxs)
+ size# (int (count c#))
+ ~gb (chunk-buffer size#)]
+ (if (loop [~gi (int 0)]
+ (if (< ~gi size#)
+ (let [~bind (.nth c# ~gi)]
+ ~(do-cmod mod-pairs))
+ true))
+ (chunk-cons
+ (chunk ~gb)
+ (~giter (chunk-rest ~gxs)))
+ (chunk-cons (chunk ~gb) nil)))
+ (let [~bind (first ~gxs)]
+ ~(do-mod mod-pairs)))))))))))]
`(let [iter# ~(emit-bind (to-groups seq-exprs))]
(iter# ~(second seq-exprs)))))
@@ -3587,7 +3780,7 @@
(defmacro with-loading-context [& body]
`((fn loading# []
(. clojure.lang.Var (pushThreadBindings {clojure.lang.Compiler/LOADER
- (-> loading# .getClass .getClassLoader)}))
+ (.getClassLoader (.getClass #^Object loading#))}))
(try
~@body
(finally
@@ -4262,9 +4455,9 @@
"clojure/version.properties")
properties (doto (new java.util.Properties) (.load version-stream))
prop (fn [k] (.getProperty properties (str "clojure.version." k)))
- clojure-version {:major (Integer/valueOf (prop "major"))
- :minor (Integer/valueOf (prop "minor"))
- :incremental (Integer/valueOf (prop "incremental"))
+ clojure-version {:major (Integer/valueOf #^String (prop "major"))
+ :minor (Integer/valueOf #^String (prop "minor"))
+ :incremental (Integer/valueOf #^String (prop "incremental"))
:qualifier (prop "qualifier")}]
(def *clojure-version*
(if (not (= (prop "interim") "false"))
@@ -4315,3 +4508,76 @@
Delivers the supplied value to the promise, releasing any pending
derefs. A subsequent call to deliver on a promise will throw an exception."
[promise val] (promise val))
+
+;;;;;;;;;;;;;;;;;;;;; editable collections ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defn transient
+ "Returns a new, transient version of the collection, in constant time."
+ [#^clojure.lang.IEditableCollection coll]
+ (.asTransient coll))
+
+(defn persistent!
+ "Returns a new, persistent version of the transient collection, in
+ constant time. The transient collection cannot be used after this
+ call, any such use will throw an exception."
+ [#^clojure.lang.ITransientCollection coll]
+ (.persistent coll))
+
+(defn conj!
+ "Adds x to the transient collection, and return coll. The 'addition'
+ may happen at different 'places' depending on the concrete type."
+ [#^clojure.lang.ITransientCollection coll x]
+ (.conj coll x))
+
+(defn assoc!
+ "When applied to a transient map, adds mapping of key(s) to
+ val(s). When applied to a transient vector, sets the val at index.