diff options
author | Rich Hickey <richhickey@gmail.com> | 2009-04-27 17:10:12 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2009-04-27 17:10:12 +0000 |
commit | be925c49b9d7c9e799711fd4caa4cf248ac16023 (patch) | |
tree | 6d71fa8d498f95176edd1dc059e7f04ccb3cf23f /src | |
parent | e8fce745c782a34f8729acea76bb191fcb41eb0f (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.clj | 19 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Stream.java | 41 |
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; } }; } + } |