Skip to content

Commit ca1765e

Browse files
committed
[lazy] added more, made filter and map use lazy-seq, made Delay.Seq implement IPersistentCollection and List
1 parent 42715f9 commit ca1765e

File tree

3 files changed

+235
-40
lines changed

3 files changed

+235
-40
lines changed

src/clj/clojure/core.clj

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@
4747
argument. If there are no more items, returns nil."}
4848
rest (fn rest [x] (. clojure.lang.RT (rest x))))
4949

50+
(def
51+
#^{:arglists '([coll])
52+
:doc "Returns a seqable collection of the items after the first. May return nil. Calls seq on its
53+
argument."}
54+
more (fn more [x] (. clojure.lang.RT (more x))))
55+
5056
(def
5157
#^{:arglists '([coll x] [coll x & xs])
5258
:doc "conj[oin]. Returns a new collection with the xs
@@ -418,6 +424,16 @@
418424
(cat (concat x y) zs))))
419425

420426
;;;;;;;;;;;;;;;;at this point all the support for syntax-quote exists;;;;;;;;;;;;;;;;;;;;;;
427+
428+
(defmacro lazy-seq
429+
"Takes a body of expressions that returns an ISeq or nil, and yields
430+
a Seqable object that will invoke the body only the first time seq
431+
is called, and will cache the result and return it on all subsequent
432+
seq calls. Any closed over locals will be cleared prior to the tail
433+
call of body."
434+
[& body]
435+
(list 'new 'clojure.lang.Delay$Seq (list* `#^{:once true} fn* [] body)))
436+
421437
(defmacro delay
422438
"Takes a body of expressions and yields a Delay object that will
423439
invoke the body only the first time it is forced (with force), and
@@ -1393,26 +1409,30 @@
13931409
not-any? (comp not some))
13941410

13951411
(defn map
1396-
"Returns a lazy seq consisting of the result of applying f to the
1412+
"Returns a lazy sequence consisting of the result of applying f to the
13971413
set of first items of each coll, followed by applying f to the set
13981414
of second items in each coll, until any one of the colls is
13991415
exhausted. Any remaining items in other colls are ignored. Function
14001416
f should accept number-of-colls arguments."
14011417
([f coll]
1402-
(when (seq coll)
1403-
(lazy-cons (f (first coll)) (map f (rest coll)))))
1418+
(lazy-seq
1419+
(when (seq coll)
1420+
(cons (f (first coll)) (map f (more coll))))))
14041421
([f c1 c2]
1405-
(when (and (seq c1) (seq c2))
1406-
(lazy-cons (f (first c1) (first c2))
1407-
(map f (rest c1) (rest c2)))))
1422+
(lazy-seq
1423+
(when (and (seq c1) (seq c2))
1424+
(cons (f (first c1) (first c2))
1425+
(map f (more c1) (more c2))))))
14081426
([f c1 c2 c3]
1409-
(when (and (seq c1) (seq c2) (seq c3))
1410-
(lazy-cons (f (first c1) (first c2) (first c3))
1411-
(map f (rest c1) (rest c2) (rest c3)))))
1427+
(lazy-seq
1428+
(when (and (seq c1) (seq c2) (seq c3))
1429+
(cons (f (first c1) (first c2) (first c3))
1430+
(map f (more c1) (more c2) (more c3))))))
14121431
([f c1 c2 c3 & colls]
14131432
(let [step (fn step [cs]
1414-
(when (every? seq cs)
1415-
(lazy-cons (map first cs) (step (map rest cs)))))]
1433+
(lazy-seq
1434+
(when (every? seq cs)
1435+
(cons (map first cs) (step (map more cs))))))]
14161436
(map #(apply f %) (step (conj colls c3 c2 c1))))))
14171437

14181438
(defn mapcat
@@ -1422,13 +1442,16 @@
14221442
(apply concat (apply map f colls)))
14231443

14241444
(defn filter
1425-
"Returns a lazy seq of the items in coll for which
1445+
"Returns a lazy sequence of the items in coll for which
14261446
(pred item) returns true. pred must be free of side-effects."
14271447
[pred coll]
1428-
(when (seq coll)
1429-
(if (pred (first coll))
1430-
(lazy-cons (first coll) (filter pred (rest coll)))
1431-
(recur pred (rest coll)))))
1448+
(let [step (fn [pred coll]
1449+
(when (seq coll)
1450+
(if (pred (first coll))
1451+
(clojure.lang.Cons. (first coll) (filter pred (more coll)))
1452+
(recur pred (more coll)))))]
1453+
(lazy-seq (step pred coll))))
1454+
14321455

14331456
(defn remove
14341457
"Returns a lazy seq of the items in coll for which

src/jvm/clojure/lang/Delay.java

Lines changed: 181 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,33 @@
1212

1313
package clojure.lang;
1414

15-
public class Delay{
16-
Object val;
17-
IFn fn;
15+
import java.util.*;
1816

19-
public Delay(IFn fn){
20-
this.fn = fn;
21-
this.val = null;
22-
}
17+
public class Delay {
18+
Object val;
19+
IFn fn;
2320

24-
static public Object force(Object x) throws Exception{
25-
return (x instanceof Delay) ?
26-
((Delay) x).get()
27-
: x;
28-
}
21+
public Delay(IFn fn) {
22+
this.fn = fn;
23+
this.val = null;
24+
}
2925

30-
synchronized Object get() throws Exception{
31-
if(fn != null)
32-
{
33-
val = fn.invoke();
34-
fn = null;
35-
}
36-
return val;
37-
}
26+
static public Object force(Object x) throws Exception {
27+
return (x instanceof Delay) ?
28+
((Delay) x).get()
29+
: x;
30+
}
3831

39-
static public class Seq extends Delay implements Seqable{
32+
synchronized Object get() throws Exception {
33+
if (fn != null)
34+
{
35+
val = fn.invoke();
36+
fn = null;
37+
}
38+
return val;
39+
}
40+
41+
static public class Seq extends Delay implements IPersistentCollection, List {
4042
public Seq(IFn fn) {
4143
super(fn);
4244
}
@@ -51,5 +53,163 @@ public ISeq seq() {
5153
throw new RuntimeException(e);
5254
}
5355
}
56+
57+
public int count() {
58+
int c = 0;
59+
for (ISeq s = seq(); s != null; s = s.rest())
60+
++c;
61+
return c;
62+
}
63+
64+
public IPersistentCollection cons(Object o) {
65+
return RT.cons(o, seq());
66+
}
67+
68+
public IPersistentCollection empty() {
69+
return null;
70+
}
71+
72+
public boolean equiv(Object o) {
73+
ISeq s = seq();
74+
return s == o || (s != null && s.equiv(o));
75+
}
76+
77+
public int hashCode() {
78+
return Util.hash(seq());
79+
}
80+
81+
public boolean equals(Object o) {
82+
ISeq s = seq();
83+
return s == o || (s != null && s.equals(o));
84+
}
85+
86+
87+
// java.util.Collection implementation
88+
89+
public Object[] toArray() {
90+
return RT.seqToArray(seq());
91+
}
92+
93+
public boolean add(Object o) {
94+
throw new UnsupportedOperationException();
95+
}
96+
97+
public boolean remove(Object o) {
98+
throw new UnsupportedOperationException();
99+
}
100+
101+
public boolean addAll(Collection c) {
102+
throw new UnsupportedOperationException();
103+
}
104+
105+
public void clear() {
106+
throw new UnsupportedOperationException();
107+
}
108+
109+
public boolean retainAll(Collection c) {
110+
throw new UnsupportedOperationException();
111+
}
112+
113+
public boolean removeAll(Collection c) {
114+
throw new UnsupportedOperationException();
115+
}
116+
117+
public boolean containsAll(Collection c) {
118+
for (Object o : c)
119+
{
120+
if (!contains(o))
121+
return false;
122+
}
123+
return true;
124+
}
125+
126+
public Object[] toArray(Object[] a) {
127+
if (a.length >= count())
128+
{
129+
ISeq s = seq();
130+
for (int i = 0; s != null; ++i, s = s.rest())
131+
{
132+
a[i] = s.first();
133+
}
134+
if (a.length > count())
135+
a[count()] = null;
136+
return a;
137+
}
138+
else
139+
return toArray();
140+
}
141+
142+
public int size() {
143+
return count();
144+
}
145+
146+
public boolean isEmpty() {
147+
return count() == 0;
148+
}
149+
150+
public boolean contains(Object o) {
151+
for (ISeq s = seq(); s != null; s = s.rest())
152+
{
153+
if (Util.equiv(s.first(), o))
154+
return true;
155+
}
156+
return false;
157+
}
158+
159+
public Iterator iterator() {
160+
return new SeqIterator(seq());
161+
}
162+
163+
//////////// List stuff /////////////////
164+
private List reify() {
165+
return new ArrayList(this);
166+
}
167+
168+
public List subList(int fromIndex, int toIndex) {
169+
return reify().subList(fromIndex, toIndex);
170+
}
171+
172+
public Object set(int index, Object element) {
173+
throw new UnsupportedOperationException();
174+
}
175+
176+
public Object remove(int index) {
177+
throw new UnsupportedOperationException();
178+
}
179+
180+
public int indexOf(Object o) {
181+
ISeq s = seq();
182+
for (int i = 0; s != null; s = s.rest(), i++)
183+
{
184+
if (Util.equiv(s.first(), o))
185+
return i;
186+
}
187+
return -1;
188+
}
189+
190+
public int lastIndexOf(Object o) {
191+
return reify().lastIndexOf(o);
192+
}
193+
194+
public ListIterator listIterator() {
195+
return reify().listIterator();
196+
}
197+
198+
public ListIterator listIterator(int index) {
199+
return reify().listIterator(index);
200+
}
201+
202+
public Object get(int index) {
203+
return RT.nth(this, index);
204+
}
205+
206+
public void add(int index, Object element) {
207+
throw new UnsupportedOperationException();
208+
}
209+
210+
public boolean addAll(int index, Collection c) {
211+
throw new UnsupportedOperationException();
212+
}
213+
54214
}
55215
}

src/jvm/clojure/lang/RT.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -528,10 +528,13 @@ static public IPersistentCollection conj(IPersistentCollection coll, Object x){
528528
}
529529

530530
static public ISeq cons(Object x, Object coll){
531-
ISeq y = seq(coll);
532-
if(y == null)
531+
//ISeq y = seq(coll);
532+
if(coll == null)
533533
return new PersistentList(x);
534-
return y.cons(x);
534+
else if (coll instanceof Seqable)
535+
return new Cons(x, (Seqable) coll);
536+
else
537+
return new Cons(x, seq(coll));
535538
}
536539

537540
static public Object first(Object x){
@@ -564,6 +567,15 @@ static public ISeq rest(Object x){
564567
return seq.rest();
565568
}
566569

570+
static public Seqable more(Object x){
571+
if(x instanceof ISeq)
572+
return ((ISeq) x).more();
573+
ISeq seq = seq(x);
574+
if(seq == null)
575+
return null;
576+
return seq.more();
577+
}
578+
567579
static public ISeq rrest(Object x){
568580
return rest(rest(x));
569581
}

0 commit comments

Comments
 (0)