summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2009-04-27 17:10:12 +0000
committerRich Hickey <richhickey@gmail.com>2009-04-27 17:10:12 +0000
commitbe925c49b9d7c9e799711fd4caa4cf248ac16023 (patch)
tree6d71fa8d498f95176edd1dc059e7f04ccb3cf23f /src
parente8fce745c782a34f8729acea76bb191fcb41eb0f (diff)
reduced promise for closed-over clearing in lazy-seq and delay, better error msg in condp, added stream?, support for streams in sequence, tweaks to Stream (streams still not for public use)
Diffstat (limited to 'src')
-rw-r--r--src/clj/clojure/core.clj19
-rw-r--r--src/jvm/clojure/lang/Stream.java41
2 files changed, 34 insertions, 26 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 1ccb0ecd..25cb5d18 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -423,8 +423,7 @@
"Takes a body of expressions that returns an ISeq or nil, and yields
a Seqable object that will invoke the body only the first time seq
is called, and will cache the result and return it on all subsequent
- seq calls. Any closed over locals will be cleared prior to the tail
- call of body."
+ seq calls."
[& body]
(list 'new 'clojure.lang.LazySeq (list* '#^{:once true} fn* [] body)))
@@ -455,8 +454,7 @@
"Takes a body of expressions and yields a Delay object that will
invoke the body only the first time it is forced (with force), and
will cache the result and return it on all subsequent force
- calls. Any closed over locals will be cleared prior to the tail call
- of body, (i.e. they will not be retained)."
+ calls."
[& body]
(list 'new 'clojure.lang.Delay (list* `#^{:once true} fn* [] body)))
@@ -1465,14 +1463,19 @@
(fn [& args] (apply f arg1 arg2 arg3 (concat more args)))))
;;;;;;;;;;;;;;;;;;; sequence fns ;;;;;;;;;;;;;;;;;;;;;;;
+(defn stream?
+ "Returns true if x is an instance of Stream"
+ [x] (instance? clojure.lang.Stream x))
+
(defn sequence
"Coerces coll to a (possibly empty) sequence, if it is not already
one. Will not force a lazy seq. (sequence nil) yields ()"
[coll]
- (if (seq? coll)
- coll
- (or (seq coll) ())))
+ (cond
+ (seq? coll) coll
+ (stream? coll) (.sequence #^clojure.lang.Stream coll)
+ :else (or (seq coll) ())))
(defn every?
"Returns true if (pred x) is logical true for every x in coll, else
@@ -3936,7 +3939,7 @@
(split-at (if (= :>> (second args)) 3 2) args)
n (count clause)]
(cond
- (= 0 n) `(throw (IllegalArgumentException. "No matching clause"))
+ (= 0 n) `(throw (IllegalArgumentException. (str "No matching clause: " ~expr)))
(= 1 n) a
(= 2 n) `(if (~pred ~a ~expr)
~b
diff --git a/src/jvm/clojure/lang/Stream.java b/src/jvm/clojure/lang/Stream.java
index 50d85d33..2976a7c6 100644
--- a/src/jvm/clojure/lang/Stream.java
+++ b/src/jvm/clojure/lang/Stream.java
@@ -16,10 +16,9 @@ final public class Stream implements Seqable, Streamable, Sequential {
static final ISeq NO_SEQ = new Cons(null, null);
- ISeq seq = NO_SEQ;
+ ISeq sequence = NO_SEQ;
final IFn src;
final IFn xform;
- Cons pushed = null;
IFn tap = null;
public Stream(IFn src){
@@ -32,27 +31,28 @@ final public class Stream implements Seqable, Streamable, Sequential {
this.xform = xform;
}
- final synchronized public ISeq seq(){
- if(seq == NO_SEQ)
+ final public ISeq seq(){
+ return sequence().seq();
+ }
+
+ final synchronized public ISeq sequence(){
+ if(sequence == NO_SEQ)
{
tap();
- seq = makeSeq(tap);
+ sequence = makeSequence(tap);
}
- return seq;
+ return sequence;
}
- static ISeq makeSeq(final IFn tap){
- return RT.seq(new LazySeq(new AFn(){
+ static ISeq makeSequence(final IFn tap){
+ return new LazySeq(new AFn(){
public Object invoke() throws Exception{
- Object v;
- do {
- v = tap.invoke();
- } while(v == RT.SKIP);
+ Object v = tap.invoke();
if(v == RT.EOS)
return null;
return new Cons(v, new LazySeq(this));
}
- }));
+ });
}
final synchronized public Stream stream() throws Exception {
@@ -68,16 +68,21 @@ final public class Stream implements Seqable, Streamable, Sequential {
static IFn makeTap(final IFn xform, final IFn src){
return new AFn(){
- public Object invoke() throws Exception{
+ final synchronized public Object invoke() throws Exception{
+ if(xform == null)
+ return src.invoke();
Object v;
+ Object xv;
do {
v = src.invoke();
- } while(v == RT.SKIP);
- if(xform == null || v == RT.EOS)
- return v;
- return xform.invoke(v);
+ if(v == RT.EOS)
+ return v;
+ xv = xform.invoke(v);
+ } while(xv == RT.SKIP);
+ return xv;
}
};
}
+
}