summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/clj/clojure/core.clj211
-rw-r--r--src/jvm/clojure/lang/ArrayChunk.java15
-rw-r--r--src/jvm/clojure/lang/ChunkBuffer.java12
-rw-r--r--src/jvm/clojure/lang/ChunkedCons.java29
-rw-r--r--src/jvm/clojure/lang/IChunk.java20
-rw-r--r--src/jvm/clojure/lang/IChunkedSeq.java2
-rw-r--r--src/jvm/clojure/lang/LazilyPersistentVector.java2
-rw-r--r--src/jvm/clojure/lang/PersistentVector.java2
8 files changed, 189 insertions, 104 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index f44fce09..8ed4aaf1 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -523,6 +523,78 @@
(if or# or# (or ~@next)))))
;;;;;;;;;;;;;;;;;;; sequence fns ;;;;;;;;;;;;;;;;;;;;;;;
+(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 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))
+
+(defn int
+ "Coerce to int"
+ {:tag Integer
+ :inline (fn [x] `(. clojure.lang.RT (intCast ~x)))}
+ [x] (. clojure.lang.RT (intCast x)))
+
+(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."
+ {:inline (fn [c i] `(. clojure.lang.RT (nth ~c ~i)))
+ :inline-arities #{2}}
+ ([coll index] (. clojure.lang.RT (nth coll index)))
+ ([coll index not-found] (. clojure.lang.RT (nth coll index not-found))))
+
+(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 (next more)
+ (recur y (first more) (next more))
+ (< y (first more)))
+ false)))
+
+(defn inc
+ "Returns a number one greater than num."
+ {: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
@@ -536,19 +608,17 @@
([f coll]
(let [s (seq coll)]
(if s
- (if (instance? clojure.lang.IReduce s)
- (. #^clojure.lang.IReduce s (reduce f))
- (reduce f (first s) (next s)))
+ (reduce f (first s) (next 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)) (next s))
- val))
- f val s)))))
+ (if s
+ (if (chunked-seq? s)
+ (recur f
+ (.reduce (chunk-first s) f val)
+ (chunk-next s))
+ (recur f (f val (first s)) (next s)))
+ val))))
(defn reverse
"Returns a seq of the items in coll in reverse order. Not lazy."
@@ -596,20 +666,6 @@
([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 (next more)
- (recur y (first more) (next more))
- (< y (first more)))
- false)))
-
(defn <=
"Returns non-nil if nums are in monotonically non-decreasing order,
otherwise false."
@@ -679,11 +735,6 @@
([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)))}
@@ -749,12 +800,6 @@
: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]
@@ -856,10 +901,7 @@
-(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
@@ -874,16 +916,6 @@
as next/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."
- {:inline (fn [c i] `(. clojure.lang.RT (nth ~c ~i)))
- :inline-arities #{2}}
- ([coll index] (. clojure.lang.RT (nth coll index)))
- ([coll index not-found] (. clojure.lang.RT (nth coll index not-found))))
-
;;map stuff
(defn contains?
@@ -1538,6 +1570,21 @@
:arglists '([pred coll])}
not-any? (comp not some))
+;will be redefed later with arg checks
+(defmacro dotimes
+ "bindings => name n
+
+ Repeatedly executes body (presumably for side-effects) with name
+ bound to integers from 0 through n-1."
+ [bindings & body]
+ (let [i (first bindings)
+ n (second bindings)]
+ `(let [n# (int ~n)]
+ (loop [~i (int 0)]
+ (when (< ~i n#)
+ ~@body
+ (recur (inc ~i)))))))
+
(defn map
"Returns a lazy sequence consisting of the result of applying f to the
set of first items of each coll, followed by applying f to the set
@@ -1547,7 +1594,14 @@
([f coll]
(lazy-seq
(when-let [s (seq coll)]
- (cons (f (first s)) (map f (rest s))))))
+ (if (chunked-seq? s)
+ (let [c (chunk-first s)
+ size (int (count c))
+ b (chunk-buffer size)]
+ (dotimes [i size]
+ (chunk-append b (f (.nth c i))))
+ (chunk-cons (chunk b) (map f (chunk-rest s))))
+ (cons (f (first s)) (map f (rest s)))))))
([f c1 c2]
(lazy-seq
(let [s1 (seq c1) s2 (seq c2)]
@@ -1575,15 +1629,21 @@
(apply concat (apply map f colls)))
(defn filter
- "Returns a lazy sequence of the items in coll for which
- (pred item) returns true. pred must be free of side-effects."
- [pred coll]
- (let [step (fn [p c]
- (when-let [s (seq c)]
- (if (p (first s))
- (cons (first s) (filter p (rest s)))
- (recur p (rest s)))))]
- (lazy-seq (step pred coll))))
+ ([pred coll]
+ (lazy-seq
+ (when-let [s (seq coll)]
+ (if (chunked-seq? s)
+ (let [c (chunk-first s)
+ size (count c)
+ b (chunk-buffer size)]
+ (dotimes [i size]
+ (when (pred (.nth c i))
+ (chunk-append b (.nth c i))))
+ (chunk-cons (chunk b) (filter pred (chunk-rest s))))
+ (let [f (first s) r (rest s)]
+ (if (pred f)
+ (cons f (filter pred r))
+ (filter pred r))))))))
(defn remove
@@ -1665,19 +1725,24 @@
"Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"
[f x] (cons x (lazy-seq (iterate f (f x)))))
-(defn range
+(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)
- (>= start (. Integer MIN_VALUE))
- (<= end (. Integer MAX_VALUE)))
- (new clojure.lang.Range start end)
- (take (- end start) (iterate inc start))))
+ ([end] (range 0 end 1))
+ ([start end] (range start end 1))
([start end step]
- (take-while (partial (if (pos? step) > <) end) (iterate (partial + step) start))))
+ (lazy-seq
+ (let [b (chunk-buffer 32)
+ comp (if (pos? step) < >)]
+ (loop [i start]
+ (if (and (< (count b) 32)
+ (comp i end))
+ (do
+ (chunk-append b i)
+ (recur (+ i step)))
+ (chunk-cons (chunk b)
+ (when (comp i end)
+ (range i end step)))))))))
(defn merge
"Returns a map that consists of the rest of the maps conj-ed onto
@@ -1952,12 +2017,6 @@
: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
@@ -4237,7 +4296,7 @@
Returns a promise object that can be read with deref/@, and set,
once only, with deliver. Calls to deref/@ prior to delivery will
block. All subsequent derefs will return the same delivered value
- without blocking."
+ without blocking."
[]
(let [d (java.util.concurrent.CountDownLatch. 1)
v (atom nil)]
diff --git a/src/jvm/clojure/lang/ArrayChunk.java b/src/jvm/clojure/lang/ArrayChunk.java
index 08f863cf..d5a5a77b 100644
--- a/src/jvm/clojure/lang/ArrayChunk.java
+++ b/src/jvm/clojure/lang/ArrayChunk.java
@@ -12,7 +12,7 @@
package clojure.lang;
-public final class ArrayChunk implements Indexed{
+public final class ArrayChunk implements IChunk{
final Object[] array;
final int off;
@@ -39,4 +39,17 @@ public Object nth(int i){
public int count(){
return end - off;
}
+
+public IChunk dropFirst(){
+ if(off==end)
+ throw new IllegalStateException("dropFirst of empty chunk");
+ return new ArrayChunk(array, off + 1, end);
+}
+
+public Object reduce(IFn f, Object start) throws Exception{
+ Object ret = f.invoke(start, array[off]);
+ for(int x = off + 1; x < end; x++)
+ ret = f.invoke(ret, array[x]);
+ return ret;
+}
}
diff --git a/src/jvm/clojure/lang/ChunkBuffer.java b/src/jvm/clojure/lang/ChunkBuffer.java
index aee01e0e..fd484c90 100644
--- a/src/jvm/clojure/lang/ChunkBuffer.java
+++ b/src/jvm/clojure/lang/ChunkBuffer.java
@@ -14,24 +14,24 @@ package clojure.lang;
final public class ChunkBuffer implements Counted{
Object[] buffer;
- int offset;
+ int end;
public ChunkBuffer(int capacity){
buffer = new Object[capacity];
- offset = 0;
+ end = 0;
}
public void add(Object o){
- buffer[offset++] = o;
+ buffer[end++] = o;
}
-public Indexed chunk(){
- ArrayChunk ret = new ArrayChunk(buffer, 0, offset);
+public IChunk chunk(){
+ ArrayChunk ret = new ArrayChunk(buffer, 0, end);
buffer = null;
return ret;
}
public int count(){
- return offset;
+ return end;
}
}
diff --git a/src/jvm/clojure/lang/ChunkedCons.java b/src/jvm/clojure/lang/ChunkedCons.java
index 37f5f47c..b52bc2b6 100644
--- a/src/jvm/clojure/lang/ChunkedCons.java
+++ b/src/jvm/clojure/lang/ChunkedCons.java
@@ -14,51 +14,44 @@ package clojure.lang;
final public class ChunkedCons extends ASeq implements IChunkedSeq{
-final Indexed chunk;
+final IChunk chunk;
final ISeq _more;
-final int offset;
-ChunkedCons(IPersistentMap meta, Indexed chunk, int offset, ISeq more){
+ChunkedCons(IPersistentMap meta, IChunk chunk, ISeq more){
super(meta);
this.chunk = chunk;
- this.offset = offset;
this._more = more;
}
-public ChunkedCons(Indexed chunk, ISeq more){
- this(chunk, 0, more);
-}
-public ChunkedCons(Indexed chunk, int offset, ISeq more){
- this.chunk = chunk;
- this.offset = offset;
- this._more = more;
+public ChunkedCons(IChunk chunk, ISeq more){
+ this(null,chunk, more);
}
public Obj withMeta(IPersistentMap meta){
if(meta != _meta)
- return new ChunkedCons(meta, chunk, offset, _more);
+ return new ChunkedCons(meta, chunk, _more);
return this;
}
public Object first(){
- return chunk.nth(offset);
+ return chunk.nth(0);
}
public ISeq next(){
- if(offset + 1 < chunk.count())
- return new ChunkedCons(chunk, offset + 1, _more);
+ if(chunk.count() > 1)
+ return new ChunkedCons(chunk.dropFirst(), _more);
return chunkedNext();
}
public ISeq more(){
- if(offset + 1 < chunk.count())
- return new ChunkedCons(chunk, offset + 1, _more);
+ if(chunk.count() > 1)
+ return new ChunkedCons(chunk.dropFirst(), _more);
if(_more == null)
return PersistentList.EMPTY;
return _more;
}
-public Indexed chunkedFirst(){
+public IChunk chunkedFirst(){
return chunk;
}
diff --git a/src/jvm/clojure/lang/IChunk.java b/src/jvm/clojure/lang/IChunk.java
new file mode 100644
index 00000000..fd667161
--- /dev/null
+++ b/src/jvm/clojure/lang/IChunk.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+ * which can be found in the file epl-v10.html 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.
+ **/
+
+/* rich Jun 18, 2009 */
+
+package clojure.lang;
+
+public interface IChunk extends Indexed{
+
+IChunk dropFirst();
+
+Object reduce(IFn f, Object start) throws Exception;
+}
diff --git a/src/jvm/clojure/lang/IChunkedSeq.java b/src/jvm/clojure/lang/IChunkedSeq.java
index f53c3534..1f69dd3f 100644
--- a/src/jvm/clojure/lang/IChunkedSeq.java
+++ b/src/jvm/clojure/lang/IChunkedSeq.java
@@ -14,7 +14,7 @@ package clojure.lang;
public interface IChunkedSeq extends ISeq{
-Indexed chunkedFirst() throws Exception;
+IChunk chunkedFirst() throws Exception;
ISeq chunkedNext() throws Exception;
diff --git a/src/jvm/clojure/lang/LazilyPersistentVector.java b/src/jvm/clojure/lang/LazilyPersistentVector.java
index 9ffd9170..f3562cae 100644
--- a/src/jvm/clojure/lang/LazilyPersistentVector.java
+++ b/src/jvm/clojure/lang/LazilyPersistentVector.java
@@ -83,7 +83,7 @@ static class ChunkedSeq extends ASeq implements IChunkedSeq, IndexedSeq{
return chunkedNext();
}
- public Indexed chunkedFirst(){
+ public IChunk chunkedFirst(){
return new ArrayChunk(array, offset, end);
}
diff --git a/src/jvm/clojure/lang/PersistentVector.java b/src/jvm/clojure/lang/PersistentVector.java
index 87bd11d7..5c662556 100644
--- a/src/jvm/clojure/lang/PersistentVector.java
+++ b/src/jvm/clojure/lang/PersistentVector.java
@@ -207,7 +207,7 @@ static public final class ChunkedSeq extends ASeq implements IChunkedSeq{
this.offset = offset;
}
- public Indexed chunkedFirst() throws Exception{
+ public IChunk chunkedFirst() throws Exception{
return new ArrayChunk(node, offset);
}