Skip to content

Commit a256e51

Browse files
committed
[lazy] use seq rather than relying on implicit seq of first/more in core sequence fns
1 parent ec0f8f3 commit a256e51

File tree

2 files changed

+104
-90
lines changed

2 files changed

+104
-90
lines changed

src/clj/clojure/core.clj

Lines changed: 102 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -417,17 +417,19 @@
417417
([x] (lazy-seq x))
418418
([x y]
419419
(lazy-seq
420-
(if (seq x)
421-
(cons (first x) (concat (more x) y))
422-
y)))
420+
(let [s (seq x)]
421+
(if s
422+
(cons (first s) (concat (more s) y))
423+
y))))
423424
([x y & zs]
424425
(let [cat (fn cat [xys zs]
425426
(lazy-seq
426-
(if (seq xys)
427-
(cons (first xys) (cat (more xys) zs))
428-
(when zs
429-
(cat (first zs) (rest zs))))))]
430-
(cat (concat x y) zs))))
427+
(let [xys (seq xys)]
428+
(if xys
429+
(cons (first xys) (cat (more xys) zs))
430+
(when zs
431+
(cat (first zs) (rest zs)))))))]
432+
(cat (concat x y) zs))))
431433

432434
;;;;;;;;;;;;;;;;at this point all the support for syntax-quote exists;;;;;;;;;;;;;;;;;;;;;;
433435

@@ -1076,6 +1078,37 @@
10761078
(when more
10771079
(list* `assert-args fnname more)))))
10781080

1081+
(defmacro if-let
1082+
"bindings => binding-form test
1083+
1084+
If test is true, evaluates then with binding-form bound to the value of test, if not, yields else"
1085+
([bindings then]
1086+
`(if-let ~bindings ~then nil))
1087+
([bindings then else & oldform]
1088+
(assert-args if-let
1089+
(and (vector? bindings) (nil? oldform)) "a vector for its binding"
1090+
(= 2 (count bindings)) "exactly 2 forms in binding vector")
1091+
(let [form (bindings 0) tst (bindings 1)]
1092+
`(let [temp# ~tst]
1093+
(if temp#
1094+
(let [~form temp#]
1095+
~then)
1096+
~else)))))
1097+
1098+
(defmacro when-let
1099+
"bindings => binding-form test
1100+
1101+
When test is true, evaluates body with binding-form bound to the value of test"
1102+
[bindings & body]
1103+
(assert-args when-let
1104+
(vector? bindings) "a vector for its binding"
1105+
(= 2 (count bindings)) "exactly 2 forms in binding vector")
1106+
(let [form (bindings 0) tst (bindings 1)]
1107+
`(let [temp# ~tst]
1108+
(when temp#
1109+
(let [~form temp#]
1110+
~@body)))))
1111+
10791112
(defmacro binding
10801113
"binding => var-symbol init-expr
10811114
@@ -1418,23 +1451,26 @@
14181451
f should accept number-of-colls arguments."
14191452
([f coll]
14201453
(lazy-seq
1421-
(when (seq coll)
1422-
(cons (f (first coll)) (map f (more coll))))))
1454+
(when-let [s (seq coll)]
1455+
(cons (f (first s)) (map f (more s))))))
14231456
([f c1 c2]
14241457
(lazy-seq
1425-
(when (and (seq c1) (seq c2))
1426-
(cons (f (first c1) (first c2))
1427-
(map f (more c1) (more c2))))))
1458+
(let [s1 (seq c1) s2 (seq c2)]
1459+
(when (and s1 s2)
1460+
(cons (f (first s1) (first s2))
1461+
(map f (more s1) (more s2)))))))
14281462
([f c1 c2 c3]
14291463
(lazy-seq
1430-
(when (and (seq c1) (seq c2) (seq c3))
1431-
(cons (f (first c1) (first c2) (first c3))
1432-
(map f (more c1) (more c2) (more c3))))))
1464+
(let [s1 (seq c1) s2 (seq c2) s3 (seq c3)]
1465+
(when (and s1 s2 s3)
1466+
(cons (f (first s1) (first s2) (first s3))
1467+
(map f (more s1) (more s2) (more s3)))))))
14331468
([f c1 c2 c3 & colls]
14341469
(let [step (fn step [cs]
14351470
(lazy-seq
1436-
(when (every? seq cs)
1437-
(cons (map first cs) (step (map more cs))))))]
1471+
(let [ss (map seq cs)]
1472+
(when (every? identity ss)
1473+
(cons (map first ss) (step (map more ss)))))))]
14381474
(map #(apply f %) (step (conj colls c3 c2 c1))))))
14391475

14401476
(defn mapcat
@@ -1447,11 +1483,11 @@
14471483
"Returns a lazy sequence of the items in coll for which
14481484
(pred item) returns true. pred must be free of side-effects."
14491485
[pred coll]
1450-
(let [step (fn [pred coll]
1451-
(when (seq coll)
1452-
(if (pred (first coll))
1453-
(clojure.lang.Cons. (first coll) (filter pred (more coll)))
1454-
(recur pred (more coll)))))]
1486+
(let [step (fn [p c]
1487+
(when-let [s (seq c)]
1488+
(if (p (first s))
1489+
(clojure.lang.Cons. (first s) (filter p (more s)))
1490+
(recur p (more s)))))]
14551491
(lazy-seq (step pred coll))))
14561492

14571493

@@ -1466,24 +1502,27 @@
14661502
there are fewer than n."
14671503
[n coll]
14681504
(lazy-seq
1469-
(when (and (pos? n) (seq coll))
1470-
(cons (first coll) (take (dec n) (more coll))))))
1505+
(when (pos? n)
1506+
(when-let [s (seq coll)]
1507+
(cons (first s) (take (dec n) (more s)))))))
14711508

14721509
(defn take-while
14731510
"Returns a lazy sequence of successive items from coll while
14741511
(pred item) returns true. pred must be free of side-effects."
14751512
[pred coll]
14761513
(lazy-seq
1477-
(when (and (seq coll) (pred (first coll)))
1478-
(cons (first coll) (take-while pred (more coll))))))
1514+
(when-let [s (seq coll)]
1515+
(when (pred (first s)))
1516+
(cons (first s) (take-while pred (more s))))))
14791517

14801518
(defn drop
14811519
"Returns a lazy sequence of all but the first n items in coll."
14821520
[n coll]
14831521
(let [step (fn [n coll]
1484-
(if (and (pos? n) (seq coll))
1485-
(recur (dec n) (more coll))
1486-
(seq coll)))]
1522+
(let [s (seq coll)]
1523+
(if (and (pos? n) s)
1524+
(recur (dec n) (more s))
1525+
s)))]
14871526
(lazy-seq (step n coll))))
14881527

14891528
(defn drop-last
@@ -1496,9 +1535,10 @@
14961535
item for which (pred item) returns nil."
14971536
[pred coll]
14981537
(let [step (fn [pred coll]
1499-
(if (and (seq coll) (pred (first coll)))
1500-
(recur pred (more coll))
1501-
(seq coll)))]
1538+
(let [s (seq coll)]
1539+
(if (and s (pred (first s)))
1540+
(recur pred (more s))
1541+
s)))]
15021542
(lazy-seq (step pred coll))))
15031543

15041544
(defn cycle
@@ -1625,10 +1665,10 @@
16251665
(partition n n coll))
16261666
([n step coll]
16271667
(lazy-seq
1628-
(when (seq coll)
1629-
(let [p (take n coll)]
1668+
(when-let [s (seq coll)]
1669+
(let [p (take n s)]
16301670
(when (= n (count p))
1631-
(cons p (partition n step (drop step coll)))))))))
1671+
(cons p (partition n step (drop step s)))))))))
16321672

16331673
;; evaluation
16341674

@@ -2374,8 +2414,8 @@
23742414
"Returns a lazy seq of every nth item in coll."
23752415
[n coll]
23762416
(lazy-seq
2377-
(when (seq coll)
2378-
(cons (first coll) (take-nth n (drop n coll))))))
2417+
(when-let [s (seq coll)]
2418+
(cons (first s) (take-nth n (drop n s))))))
23792419

23802420
(defn interleave
23812421
"Returns a lazy seq of the first item in each coll, then the second
@@ -2611,17 +2651,18 @@
26112651
`(fn ~giter [~gxs]
26122652
(lazy-seq
26132653
(loop [~gxs ~gxs]
2614-
(when-first [~(:bind group) ~gxs]
2615-
(when ~(or (:while group) true)
2616-
(if ~(or (:when group) true)
2617-
~(if more-groups
2618-
`(let [iterys# ~(emit more-groups)
2619-
fs# (seq (iterys# ~next-seq))]
2620-
(if fs#
2621-
(concat fs# (~giter (more ~gxs)))
2622-
(recur (more ~gxs))))
2623-
`(cons ~expr (~giter (more ~gxs))))
2624-
(recur (more ~gxs))))))))))]
2654+
(let [~gxs (seq ~gxs)]
2655+
(when-first [~(:bind group) ~gxs]
2656+
(when ~(or (:while group) true)
2657+
(if ~(or (:when group) true)
2658+
~(if more-groups
2659+
`(let [iterys# ~(emit more-groups)
2660+
fs# (seq (iterys# ~next-seq))]
2661+
(if fs#
2662+
(concat fs# (~giter (more ~gxs)))
2663+
(recur (more ~gxs))))
2664+
`(cons ~expr (~giter (more ~gxs))))
2665+
(recur (more ~gxs)))))))))))]
26252666
`(let [iter# ~(emit (to-groups seq-exprs))]
26262667
(iter# ~(second seq-exprs))))))
26272668

@@ -2906,43 +2947,14 @@
29062947
(let [step (fn step [xs seen]
29072948
(lazy-seq
29082949
((fn [[f :as xs] seen]
2909-
(when (seq xs)
2950+
(when-let [s (seq xs)]
29102951
(if (seen f)
2911-
(recur (more xs) seen)
2912-
(cons f (step (more xs) (conj seen f))))))
2952+
(recur (more s) seen)
2953+
(cons f (step (more s) (conj seen f))))))
29132954
xs seen)))]
29142955
(step coll #{})))
29152956

2916-
(defmacro if-let
2917-
"bindings => binding-form test
29182957

2919-
If test is true, evaluates then with binding-form bound to the value of test, if not, yields else"
2920-
([bindings then]
2921-
`(if-let ~bindings ~then nil))
2922-
([bindings then else & oldform]
2923-
(assert-args if-let
2924-
(and (vector? bindings) (nil? oldform)) "a vector for its binding"
2925-
(= 2 (count bindings)) "exactly 2 forms in binding vector")
2926-
(let [[form tst] bindings]
2927-
`(let [temp# ~tst]
2928-
(if temp#
2929-
(let [~form temp#]
2930-
~then)
2931-
~else)))))
2932-
2933-
(defmacro when-let
2934-
"bindings => binding-form test
2935-
2936-
When test is true, evaluates body with binding-form bound to the value of test"
2937-
[bindings & body]
2938-
(assert-args when-let
2939-
(vector? bindings) "a vector for its binding"
2940-
(= 2 (count bindings)) "exactly 2 forms in binding vector")
2941-
(let [[form tst] bindings]
2942-
`(let [temp# ~tst]
2943-
(when temp#
2944-
(let [~form temp#]
2945-
~@body)))))
29462958

29472959
(defn replace
29482960
"Given a map of replacement pairs and a vector/collection, returns a
@@ -3740,17 +3752,19 @@
37403752
step (fn step [[x & xs :as s]
37413753
[a & as :as acycle]]
37423754
(lazy-seq
3743-
(if s
3744-
(let [v (wget a)]
3745-
(send a (fn [_] (f x)))
3746-
(cons v (step xs as)))
3747-
(map wget (take (count agents) acycle)))))]
3755+
(let [s (seq s)]
3756+
(if s
3757+
(let [v (wget a)]
3758+
(send a (fn [_] (f x)))
3759+
(cons v (step xs as)))
3760+
(map wget (take (count agents) acycle))))))]
37483761
(step (drop n coll) (cycle agents))))
37493762
([f coll & colls]
37503763
(let [step (fn step [cs]
37513764
(lazy-seq
3752-
(when (every? seq cs)
3753-
(cons (map first cs) (step (map rest cs))))))]
3765+
(let [ss (map seq cs)]
3766+
(when (every? identity ss)
3767+
(cons (map first ss) (step (map rest ss)))))))]
37543768
(pmap #(apply f %) (step (cons coll colls))))))
37553769

37563770
(def

src/jvm/clojure/lang/Delay.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ synchronized Object get() throws Exception {
3838
return val;
3939
}
4040

41-
static public class Seq extends Delay implements IPersistentCollection, List, Sequential, Sequence {
41+
static public class Seq extends Delay implements List, Sequence {
4242
public Seq(IFn fn) {
4343
super(fn);
4444
}
4545

4646
public ISeq seq() {
4747
try
4848
{
49-
return (ISeq) get();
49+
return RT.seq(get());
5050
}
5151
catch (Exception e)
5252
{

0 commit comments

Comments
 (0)