summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2009-02-11 18:59:53 +0000
committerRich Hickey <richhickey@gmail.com>2009-02-11 18:59:53 +0000
commita256e51ef5e7f48e1f9fd4f0c4a1ba4bf1ccf6a2 (patch)
tree5fb8cb0e19bb988f1a3da923745258490402d92b
parentec0f8f3a1c2009175966819690dd34b53aeefae0 (diff)
[lazy] use seq rather than relying on implicit seq of first/more in core sequence fns
-rw-r--r--src/clj/clojure/core.clj190
-rw-r--r--src/jvm/clojure/lang/Delay.java4
2 files changed, 104 insertions, 90 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index c0413c5d..3daccc6b 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -417,17 +417,19 @@
([x] (lazy-seq x))
([x y]
(lazy-seq
- (if (seq x)
- (cons (first x) (concat (more x) y))
- y)))
+ (let [s (seq x)]
+ (if s
+ (cons (first s) (concat (more s) y))
+ y))))
([x y & zs]
(let [cat (fn cat [xys zs]
(lazy-seq
- (if (seq xys)
- (cons (first xys) (cat (more xys) zs))
- (when zs
- (cat (first zs) (rest zs))))))]
- (cat (concat x y) zs))))
+ (let [xys (seq xys)]
+ (if xys
+ (cons (first xys) (cat (more xys) zs))
+ (when zs
+ (cat (first zs) (rest zs)))))))]
+ (cat (concat x y) zs))))
;;;;;;;;;;;;;;;;at this point all the support for syntax-quote exists;;;;;;;;;;;;;;;;;;;;;;
@@ -1076,6 +1078,37 @@
(when more
(list* `assert-args fnname more)))))
+(defmacro if-let
+ "bindings => binding-form test
+
+ If test is true, evaluates then with binding-form bound to the value of test, if not, yields else"
+ ([bindings then]
+ `(if-let ~bindings ~then nil))
+ ([bindings then else & oldform]
+ (assert-args if-let
+ (and (vector? bindings) (nil? oldform)) "a vector for its binding"
+ (= 2 (count bindings)) "exactly 2 forms in binding vector")
+ (let [form (bindings 0) tst (bindings 1)]
+ `(let [temp# ~tst]
+ (if temp#
+ (let [~form temp#]
+ ~then)
+ ~else)))))
+
+(defmacro when-let
+ "bindings => binding-form test
+
+ When test is true, evaluates body with binding-form bound to the value of test"
+ [bindings & body]
+ (assert-args when-let
+ (vector? bindings) "a vector for its binding"
+ (= 2 (count bindings)) "exactly 2 forms in binding vector")
+ (let [form (bindings 0) tst (bindings 1)]
+ `(let [temp# ~tst]
+ (when temp#
+ (let [~form temp#]
+ ~@body)))))
+
(defmacro binding
"binding => var-symbol init-expr
@@ -1418,23 +1451,26 @@
f should accept number-of-colls arguments."
([f coll]
(lazy-seq
- (when (seq coll)
- (cons (f (first coll)) (map f (more coll))))))
+ (when-let [s (seq coll)]
+ (cons (f (first s)) (map f (more s))))))
([f c1 c2]
(lazy-seq
- (when (and (seq c1) (seq c2))
- (cons (f (first c1) (first c2))
- (map f (more c1) (more c2))))))
+ (let [s1 (seq c1) s2 (seq c2)]
+ (when (and s1 s2)
+ (cons (f (first s1) (first s2))
+ (map f (more s1) (more s2)))))))
([f c1 c2 c3]
(lazy-seq
- (when (and (seq c1) (seq c2) (seq c3))
- (cons (f (first c1) (first c2) (first c3))
- (map f (more c1) (more c2) (more c3))))))
+ (let [s1 (seq c1) s2 (seq c2) s3 (seq c3)]
+ (when (and s1 s2 s3)
+ (cons (f (first s1) (first s2) (first s3))
+ (map f (more s1) (more s2) (more s3)))))))
([f c1 c2 c3 & colls]
(let [step (fn step [cs]
(lazy-seq
- (when (every? seq cs)
- (cons (map first cs) (step (map more cs))))))]
+ (let [ss (map seq cs)]
+ (when (every? identity ss)
+ (cons (map first ss) (step (map more ss)))))))]
(map #(apply f %) (step (conj colls c3 c2 c1))))))
(defn mapcat
@@ -1447,11 +1483,11 @@
"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 [pred coll]
- (when (seq coll)
- (if (pred (first coll))
- (clojure.lang.Cons. (first coll) (filter pred (more coll)))
- (recur pred (more coll)))))]
+ (let [step (fn [p c]
+ (when-let [s (seq c)]
+ (if (p (first s))
+ (clojure.lang.Cons. (first s) (filter p (more s)))
+ (recur p (more s)))))]
(lazy-seq (step pred coll))))
@@ -1466,24 +1502,27 @@
there are fewer than n."
[n coll]
(lazy-seq
- (when (and (pos? n) (seq coll))
- (cons (first coll) (take (dec n) (more coll))))))
+ (when (pos? n)
+ (when-let [s (seq coll)]
+ (cons (first s) (take (dec n) (more s)))))))
(defn take-while
"Returns a lazy sequence of successive items from coll while
(pred item) returns true. pred must be free of side-effects."
[pred coll]
(lazy-seq
- (when (and (seq coll) (pred (first coll)))
- (cons (first coll) (take-while pred (more coll))))))
+ (when-let [s (seq coll)]
+ (when (pred (first s)))
+ (cons (first s) (take-while pred (more s))))))
(defn drop
"Returns a lazy sequence of all but the first n items in coll."
[n coll]
(let [step (fn [n coll]
- (if (and (pos? n) (seq coll))
- (recur (dec n) (more coll))
- (seq coll)))]
+ (let [s (seq coll)]
+ (if (and (pos? n) s)
+ (recur (dec n) (more s))
+ s)))]
(lazy-seq (step n coll))))
(defn drop-last
@@ -1496,9 +1535,10 @@
item for which (pred item) returns nil."
[pred coll]
(let [step (fn [pred coll]
- (if (and (seq coll) (pred (first coll)))
- (recur pred (more coll))
- (seq coll)))]
+ (let [s (seq coll)]
+ (if (and s (pred (first s)))
+ (recur pred (more s))
+ s)))]
(lazy-seq (step pred coll))))
(defn cycle
@@ -1625,10 +1665,10 @@
(partition n n coll))
([n step coll]
(lazy-seq
- (when (seq coll)
- (let [p (take n coll)]
+ (when-let [s (seq coll)]
+ (let [p (take n s)]
(when (= n (count p))
- (cons p (partition n step (drop step coll)))))))))
+ (cons p (partition n step (drop step s)))))))))
;; evaluation
@@ -2374,8 +2414,8 @@
"Returns a lazy seq of every nth item in coll."
[n coll]
(lazy-seq
- (when (seq coll)
- (cons (first coll) (take-nth n (drop n coll))))))
+ (when-let [s (seq coll)]
+ (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
@@ -2611,17 +2651,18 @@
`(fn ~giter [~gxs]
(lazy-seq
(loop [~gxs ~gxs]
- (when-first [~(:bind group) ~gxs]
- (when ~(or (:while group) true)
- (if ~(or (:when group) true)
- ~(if more-groups
- `(let [iterys# ~(emit more-groups)
- fs# (seq (iterys# ~next-seq))]
- (if fs#
- (concat fs# (~giter (more ~gxs)))
- (recur (more ~gxs))))
- `(cons ~expr (~giter (more ~gxs))))
- (recur (more ~gxs))))))))))]
+ (let [~gxs (seq ~gxs)]
+ (when-first [~(:bind group) ~gxs]
+ (when ~(or (:while group) true)
+ (if ~(or (:when group) true)
+ ~(if more-groups
+ `(let [iterys# ~(emit more-groups)
+ fs# (seq (iterys# ~next-seq))]
+ (if fs#
+ (concat fs# (~giter (more ~gxs)))
+ (recur (more ~gxs))))
+ `(cons ~expr (~giter (more ~gxs))))
+ (recur (more ~gxs)))))))))))]
`(let [iter# ~(emit (to-groups seq-exprs))]
(iter# ~(second seq-exprs))))))
@@ -2906,43 +2947,14 @@
(let [step (fn step [xs seen]
(lazy-seq
((fn [[f :as xs] seen]
- (when (seq xs)
+ (when-let [s (seq xs)]
(if (seen f)
- (recur (more xs) seen)
- (cons f (step (more xs) (conj seen f))))))
+ (recur (more s) seen)
+ (cons f (step (more s) (conj seen f))))))
xs seen)))]
(step coll #{})))
-(defmacro if-let
- "bindings => binding-form test
- If test is true, evaluates then with binding-form bound to the value of test, if not, yields else"
- ([bindings then]
- `(if-let ~bindings ~then nil))
- ([bindings then else & oldform]
- (assert-args if-let
- (and (vector? bindings) (nil? oldform)) "a vector for its binding"
- (= 2 (count bindings)) "exactly 2 forms in binding vector")
- (let [[form tst] bindings]
- `(let [temp# ~tst]
- (if temp#
- (let [~form temp#]
- ~then)
- ~else)))))
-
-(defmacro when-let
- "bindings => binding-form test
-
- When test is true, evaluates body with binding-form bound to the value of test"
- [bindings & body]
- (assert-args when-let
- (vector? bindings) "a vector for its binding"
- (= 2 (count bindings)) "exactly 2 forms in binding vector")
- (let [[form tst] bindings]
- `(let [temp# ~tst]
- (when temp#
- (let [~form temp#]
- ~@body)))))
(defn replace
"Given a map of replacement pairs and a vector/collection, returns a
@@ -3740,17 +3752,19 @@
step (fn step [[x & xs :as s]
[a & as :as acycle]]
(lazy-seq
- (if s
- (let [v (wget a)]
- (send a (fn [_] (f x)))
- (cons v (step xs as)))
- (map wget (take (count agents) acycle)))))]
+ (let [s (seq s)]
+ (if s
+ (let [v (wget a)]
+ (send a (fn [_] (f x)))
+ (cons v (step xs as)))
+ (map wget (take (count agents) acycle))))))]
(step (drop n coll) (cycle agents))))
([f coll & colls]
(let [step (fn step [cs]
(lazy-seq
- (when (every? seq cs)
- (cons (map first cs) (step (map rest cs))))))]
+ (let [ss (map seq cs)]
+ (when (every? identity ss)
+ (cons (map first ss) (step (map rest ss)))))))]
(pmap #(apply f %) (step (cons coll colls))))))
(def
diff --git a/src/jvm/clojure/lang/Delay.java b/src/jvm/clojure/lang/Delay.java
index c1bacc99..53569e43 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, Sequential, Sequence {
+ static public class Seq extends Delay implements List, Sequence {
public Seq(IFn fn) {
super(fn);
}
@@ -46,7 +46,7 @@ public class Delay {
public ISeq seq() {
try
{
- return (ISeq) get();
+ return RT.seq(get());
}
catch (Exception e)
{