diff options
author | Rich Hickey <richhickey@gmail.com> | 2009-01-31 18:44:25 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2009-01-31 18:44:25 +0000 |
commit | 961bb483ff08f6508390a6467d0758efe2c1ba85 (patch) | |
tree | 7fbf968661933bb3760053fad057c63e0de2dc5c /src | |
parent | ca1765e542a2c668512f67b99ef1e50c4b1b313e (diff) |
[lazy] switched concat to lazy-seq, added Sequence, printing of sequences, more returns non-nil
Diffstat (limited to 'src')
-rw-r--r-- | src/clj/clojure/core.clj | 38 | ||||
-rw-r--r-- | src/clj/clojure/core_print.clj | 12 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 2 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Delay.java | 2 | ||||
-rw-r--r-- | src/jvm/clojure/lang/ISeq.java | 2 | ||||
-rw-r--r-- | src/jvm/clojure/lang/LispReader.java | 24 | ||||
-rw-r--r-- | src/jvm/clojure/lang/PersistentList.java | 2 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 30 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Sequence.java | 16 |
9 files changed, 88 insertions, 40 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index d95e3972..3d13eba0 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -407,32 +407,36 @@ [first-expr & rest-expr] (list 'new 'clojure.lang.LazyCons (list `fn (list [] first-expr) (list* [(gensym)] rest-expr)))) + +(defmacro lazy-seq + "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." + [& body] + (list 'new 'clojure.lang.Delay$Seq (list* '#^{:once true} fn* [] body))) + (defn concat - "Returns a lazy seq representing the concatenation of the elements in the supplied colls." + "Returns a lazy sequence representing the concatenation of the elements in the supplied colls." ([] nil) ([x] (seq x)) ([x y] - (if (seq x) - (lazy-cons (first x) (concat (rest x) y)) - (seq y))) + (lazy-seq + (if (seq x) + (cons (first x) (concat (more x) y)) + (seq y)))) ([x y & zs] (let [cat (fn cat [xys zs] - (if (seq xys) - (lazy-cons (first xys) (cat (rest xys) zs)) - (when zs - (recur (first zs) (rest zs)))))] + (lazy-seq + (if (seq xys) + (cons (first xys) (cat (more xys) zs)) + (when zs + (seq (cat (first zs) (rest zs)))))))] (cat (concat x y) zs)))) ;;;;;;;;;;;;;;;;at this point all the support for syntax-quote exists;;;;;;;;;;;;;;;;;;;;;; -(defmacro lazy-seq - "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." - [& body] - (list 'new 'clojure.lang.Delay$Seq (list* `#^{:once true} fn* [] body))) (defmacro delay "Takes a body of expressions and yields a Delay object that will @@ -3726,7 +3730,7 @@ the coordination overhead." ([f coll] (let [n (inc (.. Runtime getRuntime availableProcessors)) - agents (doall (map #(agent (f %)) (take n coll))) + agents (doall (map #(send (agent %) f) (take n coll))) wget (fn [a] (await1 a) @a) step (fn step [[x & xs :as s] [a & as :as acycle]] diff --git a/src/clj/clojure/core_print.clj b/src/clj/clojure/core_print.clj index 7a79a903..59b045b3 100644 --- a/src/clj/clojure/core_print.clj +++ b/src/clj/clojure/core_print.clj @@ -128,14 +128,18 @@ (defmethod print-dup clojure.lang.Var [#^clojure.lang.Var o, #^Writer w] (.write w (str "#=(var " (.name (.ns o)) "/" (.sym o) ")"))) -(defmethod print-method clojure.lang.ISeq [o, #^Writer w] +(defmethod print-method clojure.lang.Sequence [o, #^Writer w] (print-meta o w) (print-sequential "(" pr-on " " ")" o w)) -(defmethod print-dup clojure.lang.ISeq [o w] (print-method o w)) +(defmethod print-dup clojure.lang.Sequence [o w] (print-method o w)) (defmethod print-dup clojure.lang.IPersistentList [o w] (print-method o w)) -(prefer-method print-method clojure.lang.IPersistentList clojure.lang.ISeq) -(prefer-method print-dup clojure.lang.IPersistentList clojure.lang.ISeq) +(prefer-method print-method clojure.lang.IPersistentList clojure.lang.Sequence) +(prefer-method print-dup clojure.lang.IPersistentList clojure.lang.Sequence) +(prefer-method print-method clojure.lang.Sequence clojure.lang.IPersistentCollection) +(prefer-method print-dup clojure.lang.Sequence clojure.lang.IPersistentCollection) +(prefer-method print-method clojure.lang.Sequence java.util.Collection) +(prefer-method print-dup clojure.lang.Sequence java.util.Collection) (defmethod print-method clojure.lang.IPersistentList [o, #^Writer w] (print-meta o w) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 50921f7f..efd52ab6 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -3960,6 +3960,8 @@ private static Expr analyze(C context, Object form, String name) throws Exceptio //todo symbol macro expansion? try { + if(form instanceof Sequence) + form = RT.seq(form); if(form == null) return NIL_EXPR; else if(form == Boolean.TRUE) diff --git a/src/jvm/clojure/lang/Delay.java b/src/jvm/clojure/lang/Delay.java index 83e58a37..c1bacc99 100644 --- a/src/jvm/clojure/lang/Delay.java +++ b/src/jvm/clojure/lang/Delay.java @@ -38,7 +38,7 @@ public class Delay { return val; } - static public class Seq extends Delay implements IPersistentCollection, List { + static public class Seq extends Delay implements IPersistentCollection, List, Sequential, Sequence { public Seq(IFn fn) { super(fn); } diff --git a/src/jvm/clojure/lang/ISeq.java b/src/jvm/clojure/lang/ISeq.java index 4a24b2b1..2db905ef 100644 --- a/src/jvm/clojure/lang/ISeq.java +++ b/src/jvm/clojure/lang/ISeq.java @@ -16,7 +16,7 @@ package clojure.lang; * ISeqs are immutable values, i.e. neither first(), nor rest() changes
* or invalidates the ISeq
*/
-public interface ISeq extends IPersistentCollection, Sequential{
+public interface ISeq extends IPersistentCollection, Sequential, Sequence{
Object first();
diff --git a/src/jvm/clojure/lang/LispReader.java b/src/jvm/clojure/lang/LispReader.java index 922d1cbf..49400339 100644 --- a/src/jvm/clojure/lang/LispReader.java +++ b/src/jvm/clojure/lang/LispReader.java @@ -28,6 +28,7 @@ static final Symbol THE_VAR = Symbol.create("var"); static Symbol UNQUOTE = Symbol.create("clojure.core", "unquote");
//static Symbol UNQUOTE_SPLICING = Symbol.create(null, "unquote-splicing");
static Symbol CONCAT = Symbol.create("clojure.core", "concat");
+static Symbol SEQ = Symbol.create("clojure.core", "seq");
static Symbol LIST = Symbol.create("clojure.core", "list");
static Symbol APPLY = Symbol.create("clojure.core", "apply");
static Symbol HASHMAP = Symbol.create("clojure.core", "hash-map");
@@ -61,7 +62,7 @@ static Var GENSYM_ENV = Var.create(null); //sorted-map num->gensymbol
static Var ARG_ENV = Var.create(null);
-static
+ static
{
macros['"'] = new StringReader();
macros[';'] = new CommentReader();
@@ -702,20 +703,23 @@ public static class SyntaxQuoteReader extends AFn{ if(form instanceof IPersistentMap)
{
IPersistentVector keyvals = flattenMap(form);
- ret = RT.list(APPLY, HASHMAP, RT.cons(CONCAT, sqExpandList(keyvals.seq())));
+ ret = RT.list(APPLY, HASHMAP, RT.list(SEQ, RT.cons(CONCAT, sqExpandList(keyvals.seq()))));
}
else if(form instanceof IPersistentVector)
- {
- ret = RT.list(APPLY, VECTOR, RT.cons(CONCAT, sqExpandList(((IPersistentVector) form).seq())));
- }
+ {
+ ret = RT.list(APPLY, VECTOR, RT.list(SEQ, RT.cons(CONCAT, sqExpandList(((IPersistentVector) form).seq()))));
+ }
else if(form instanceof IPersistentSet)
- {
- ret = RT.list(APPLY, HASHSET, RT.cons(CONCAT, sqExpandList(((IPersistentSet) form).seq())));
- }
- else if(form instanceof ISeq)
+ {
+ ret = RT.list(APPLY, HASHSET, RT.list(SEQ, RT.cons(CONCAT, sqExpandList(((IPersistentSet) form).seq()))));
+ }
+ else if(form instanceof Sequence)
{
ISeq seq = RT.seq(form);
- ret = RT.cons(CONCAT, sqExpandList(seq));
+ if(seq == null)
+ ret = RT.cons(LIST,null);
+ else
+ ret = RT.list(SEQ, RT.cons(CONCAT, sqExpandList(seq)));
}
else
throw new UnsupportedOperationException("Unknown Collection type");
diff --git a/src/jvm/clojure/lang/PersistentList.java b/src/jvm/clojure/lang/PersistentList.java index 7fa3e859..26f7fea3 100644 --- a/src/jvm/clojure/lang/PersistentList.java +++ b/src/jvm/clojure/lang/PersistentList.java @@ -114,7 +114,7 @@ public Object reduce(IFn f, Object start) throws Exception{ -static class EmptyList extends Obj implements IPersistentList, List{
+static class EmptyList extends Obj implements IPersistentList, List, Sequence{
public int hashCode(){
return 1;
diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index 9ec66cae..d64cfa7d 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -453,6 +453,15 @@ static public ISeq seq(Object coll){ return seqFrom(coll); } +static public Sequence sequence(Object coll){ + if(coll == null) + return null; + else if(coll instanceof Sequence) + return (Sequence) coll; + else + return seq(coll); + } + static public IStream stream(final Object coll) throws Exception{ if(coll == null) return EMPTY_STREAM; @@ -568,12 +577,21 @@ static public ISeq rest(Object x){ } static public Seqable more(Object x){ + Seqable ret = null; if(x instanceof ISeq) - return ((ISeq) x).more(); - ISeq seq = seq(x); - if(seq == null) - return null; - return seq.more(); + ret = ((ISeq) x).more(); + else + { + ISeq seq = seq(x); + if(seq == null) + ret = PersistentList.EMPTY; + else + ret = seq.more(); + } + if(ret == null) + ret = PersistentList.EMPTY; +// throw new IllegalStateException("nil more"); + return ret; } static public ISeq rrest(Object x){ @@ -1226,7 +1244,7 @@ static public void print(Object x, Writer w) throws Exception{ } if(x == null) w.write("nil"); - else if(x instanceof ISeq || x instanceof IPersistentList) + else if(x instanceof Sequence || x instanceof IPersistentList) { w.write('('); printInnerSeq(seq(x), w); diff --git a/src/jvm/clojure/lang/Sequence.java b/src/jvm/clojure/lang/Sequence.java new file mode 100644 index 00000000..688cec53 --- /dev/null +++ b/src/jvm/clojure/lang/Sequence.java @@ -0,0 +1,16 @@ +/** + * 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 Jan 29, 2009 */ + +package clojure.lang; + +public interface Sequence { +} |