Mercurial > lasercutter
comparison src/clojure/lang/APersistentVector.java @ 10:ef7dbbd6452c
added clojure source goodness
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 21 Aug 2010 06:25:44 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
9:35cf337adfcf | 10:ef7dbbd6452c |
---|---|
1 /** | |
2 * Copyright (c) Rich Hickey. All rights reserved. | |
3 * The use and distribution terms for this software are covered by the | |
4 * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) | |
5 * which can be found in the file epl-v10.html at the root of this distribution. | |
6 * By using this software in any fashion, you are agreeing to be bound by | |
7 * the terms of this license. | |
8 * You must not remove this notice, or any other, from this software. | |
9 **/ | |
10 | |
11 /* rich Dec 18, 2007 */ | |
12 | |
13 package clojure.lang; | |
14 | |
15 import java.io.Serializable; | |
16 import java.util.*; | |
17 | |
18 public abstract class APersistentVector extends AFn implements IPersistentVector, Iterable, | |
19 List, | |
20 RandomAccess, Comparable, | |
21 Serializable { | |
22 int _hash = -1; | |
23 | |
24 public String toString(){ | |
25 return RT.printString(this); | |
26 } | |
27 | |
28 public ISeq seq(){ | |
29 if(count() > 0) | |
30 return new Seq(this, 0); | |
31 return null; | |
32 } | |
33 | |
34 public ISeq rseq(){ | |
35 if(count() > 0) | |
36 return new RSeq(this, count() - 1); | |
37 return null; | |
38 } | |
39 | |
40 static boolean doEquals(IPersistentVector v, Object obj){ | |
41 if(v == obj) return true; | |
42 if(obj instanceof List || obj instanceof IPersistentVector) | |
43 { | |
44 Collection ma = (Collection) obj; | |
45 if(ma.size() != v.count() || ma.hashCode() != v.hashCode()) | |
46 return false; | |
47 for(Iterator i1 = ((List) v).iterator(), i2 = ma.iterator(); | |
48 i1.hasNext();) | |
49 { | |
50 if(!Util.equals(i1.next(), i2.next())) | |
51 return false; | |
52 } | |
53 return true; | |
54 } | |
55 // if(obj instanceof IPersistentVector) | |
56 // { | |
57 // IPersistentVector ma = (IPersistentVector) obj; | |
58 // if(ma.count() != v.count() || ma.hashCode() != v.hashCode()) | |
59 // return false; | |
60 // for(int i = 0; i < v.count(); i++) | |
61 // { | |
62 // if(!Util.equal(v.nth(i), ma.nth(i))) | |
63 // return false; | |
64 // } | |
65 // } | |
66 else | |
67 { | |
68 if(!(obj instanceof Sequential)) | |
69 return false; | |
70 ISeq ms = RT.seq(obj); | |
71 for(int i = 0; i < v.count(); i++, ms = ms.next()) | |
72 { | |
73 if(ms == null || !Util.equals(v.nth(i), ms.first())) | |
74 return false; | |
75 } | |
76 if(ms != null) | |
77 return false; | |
78 } | |
79 | |
80 return true; | |
81 | |
82 } | |
83 | |
84 static boolean doEquiv(IPersistentVector v, Object obj){ | |
85 if(obj instanceof List || obj instanceof IPersistentVector) | |
86 { | |
87 Collection ma = (Collection) obj; | |
88 if(ma.size() != v.count()) | |
89 return false; | |
90 for(Iterator i1 = ((List) v).iterator(), i2 = ma.iterator(); | |
91 i1.hasNext();) | |
92 { | |
93 if(!Util.equiv(i1.next(), i2.next())) | |
94 return false; | |
95 } | |
96 return true; | |
97 } | |
98 // if(obj instanceof IPersistentVector) | |
99 // { | |
100 // IPersistentVector ma = (IPersistentVector) obj; | |
101 // if(ma.count() != v.count() || ma.hashCode() != v.hashCode()) | |
102 // return false; | |
103 // for(int i = 0; i < v.count(); i++) | |
104 // { | |
105 // if(!Util.equal(v.nth(i), ma.nth(i))) | |
106 // return false; | |
107 // } | |
108 // } | |
109 else | |
110 { | |
111 if(!(obj instanceof Sequential)) | |
112 return false; | |
113 ISeq ms = RT.seq(obj); | |
114 for(int i = 0; i < v.count(); i++, ms = ms.next()) | |
115 { | |
116 if(ms == null || !Util.equiv(v.nth(i), ms.first())) | |
117 return false; | |
118 } | |
119 if(ms != null) | |
120 return false; | |
121 } | |
122 | |
123 return true; | |
124 | |
125 } | |
126 | |
127 public boolean equals(Object obj){ | |
128 return doEquals(this, obj); | |
129 } | |
130 | |
131 public boolean equiv(Object obj){ | |
132 return doEquiv(this, obj); | |
133 } | |
134 | |
135 public int hashCode(){ | |
136 if(_hash == -1) | |
137 { | |
138 int hash = 1; | |
139 Iterator i = iterator(); | |
140 while(i.hasNext()) | |
141 { | |
142 Object obj = i.next(); | |
143 hash = 31 * hash + (obj == null ? 0 : obj.hashCode()); | |
144 } | |
145 // int hash = 0; | |
146 // for(int i = 0; i < count(); i++) | |
147 // { | |
148 // hash = Util.hashCombine(hash, Util.hash(nth(i))); | |
149 // } | |
150 this._hash = hash; | |
151 } | |
152 return _hash; | |
153 } | |
154 | |
155 public Object get(int index){ | |
156 return nth(index); | |
157 } | |
158 | |
159 public Object nth(int i, Object notFound){ | |
160 if(i >= 0 && i < count()) | |
161 return nth(i); | |
162 return notFound; | |
163 } | |
164 | |
165 public Object remove(int i){ | |
166 throw new UnsupportedOperationException(); | |
167 } | |
168 | |
169 public int indexOf(Object o){ | |
170 for(int i = 0; i < count(); i++) | |
171 if(Util.equiv(nth(i), o)) | |
172 return i; | |
173 return -1; | |
174 } | |
175 | |
176 public int lastIndexOf(Object o){ | |
177 for(int i = count() - 1; i >= 0; i--) | |
178 if(Util.equiv(nth(i), o)) | |
179 return i; | |
180 return -1; | |
181 } | |
182 | |
183 public ListIterator listIterator(){ | |
184 return listIterator(0); | |
185 } | |
186 | |
187 public ListIterator listIterator(final int index){ | |
188 return new ListIterator(){ | |
189 int nexti = index; | |
190 | |
191 public boolean hasNext(){ | |
192 return nexti < count(); | |
193 } | |
194 | |
195 public Object next(){ | |
196 return nth(nexti++); | |
197 } | |
198 | |
199 public boolean hasPrevious(){ | |
200 return nexti > 0; | |
201 } | |
202 | |
203 public Object previous(){ | |
204 return nth(--nexti); | |
205 } | |
206 | |
207 public int nextIndex(){ | |
208 return nexti; | |
209 } | |
210 | |
211 public int previousIndex(){ | |
212 return nexti - 1; | |
213 } | |
214 | |
215 public void remove(){ | |
216 throw new UnsupportedOperationException(); | |
217 } | |
218 | |
219 public void set(Object o){ | |
220 throw new UnsupportedOperationException(); | |
221 } | |
222 | |
223 public void add(Object o){ | |
224 throw new UnsupportedOperationException(); | |
225 } | |
226 }; | |
227 } | |
228 | |
229 public List subList(int fromIndex, int toIndex){ | |
230 return (List) RT.subvec(this, fromIndex, toIndex); | |
231 } | |
232 | |
233 | |
234 public Object set(int i, Object o){ | |
235 throw new UnsupportedOperationException(); | |
236 } | |
237 | |
238 public void add(int i, Object o){ | |
239 throw new UnsupportedOperationException(); | |
240 } | |
241 | |
242 public boolean addAll(int i, Collection c){ | |
243 throw new UnsupportedOperationException(); | |
244 } | |
245 | |
246 | |
247 public Object invoke(Object arg1) throws Exception{ | |
248 if(Util.isInteger(arg1)) | |
249 return nth(((Number) arg1).intValue()); | |
250 throw new IllegalArgumentException("Key must be integer"); | |
251 } | |
252 | |
253 public Iterator iterator(){ | |
254 //todo - something more efficient | |
255 return new Iterator(){ | |
256 int i = 0; | |
257 | |
258 public boolean hasNext(){ | |
259 return i < count(); | |
260 } | |
261 | |
262 public Object next(){ | |
263 return nth(i++); | |
264 } | |
265 | |
266 public void remove(){ | |
267 throw new UnsupportedOperationException(); | |
268 } | |
269 }; | |
270 } | |
271 | |
272 public Object peek(){ | |
273 if(count() > 0) | |
274 return nth(count() - 1); | |
275 return null; | |
276 } | |
277 | |
278 public boolean containsKey(Object key){ | |
279 if(!(Util.isInteger(key))) | |
280 return false; | |
281 int i = ((Number) key).intValue(); | |
282 return i >= 0 && i < count(); | |
283 } | |
284 | |
285 public IMapEntry entryAt(Object key){ | |
286 if(Util.isInteger(key)) | |
287 { | |
288 int i = ((Number) key).intValue(); | |
289 if(i >= 0 && i < count()) | |
290 return new MapEntry(key, nth(i)); | |
291 } | |
292 return null; | |
293 } | |
294 | |
295 public IPersistentVector assoc(Object key, Object val){ | |
296 if(Util.isInteger(key)) | |
297 { | |
298 int i = ((Number) key).intValue(); | |
299 return assocN(i, val); | |
300 } | |
301 throw new IllegalArgumentException("Key must be integer"); | |
302 } | |
303 | |
304 public Object valAt(Object key, Object notFound){ | |
305 if(Util.isInteger(key)) | |
306 { | |
307 int i = ((Number) key).intValue(); | |
308 if(i >= 0 && i < count()) | |
309 return nth(i); | |
310 } | |
311 return notFound; | |
312 } | |
313 | |
314 public Object valAt(Object key){ | |
315 return valAt(key, null); | |
316 } | |
317 | |
318 // java.util.Collection implementation | |
319 | |
320 public Object[] toArray(){ | |
321 return RT.seqToArray(seq()); | |
322 } | |
323 | |
324 public boolean add(Object o){ | |
325 throw new UnsupportedOperationException(); | |
326 } | |
327 | |
328 public boolean remove(Object o){ | |
329 throw new UnsupportedOperationException(); | |
330 } | |
331 | |
332 public boolean addAll(Collection c){ | |
333 throw new UnsupportedOperationException(); | |
334 } | |
335 | |
336 public void clear(){ | |
337 throw new UnsupportedOperationException(); | |
338 } | |
339 | |
340 public boolean retainAll(Collection c){ | |
341 throw new UnsupportedOperationException(); | |
342 } | |
343 | |
344 public boolean removeAll(Collection c){ | |
345 throw new UnsupportedOperationException(); | |
346 } | |
347 | |
348 public boolean containsAll(Collection c){ | |
349 for(Object o : c) | |
350 { | |
351 if(!contains(o)) | |
352 return false; | |
353 } | |
354 return true; | |
355 } | |
356 | |
357 public Object[] toArray(Object[] a){ | |
358 if(a.length >= count()) | |
359 { | |
360 ISeq s = seq(); | |
361 for(int i = 0; s != null; ++i, s = s.next()) | |
362 { | |
363 a[i] = s.first(); | |
364 } | |
365 if(a.length > count()) | |
366 a[count()] = null; | |
367 return a; | |
368 } | |
369 else | |
370 return toArray(); | |
371 } | |
372 | |
373 public int size(){ | |
374 return count(); | |
375 } | |
376 | |
377 public boolean isEmpty(){ | |
378 return count() == 0; | |
379 } | |
380 | |
381 public boolean contains(Object o){ | |
382 for(ISeq s = seq(); s != null; s = s.next()) | |
383 { | |
384 if(Util.equiv(s.first(), o)) | |
385 return true; | |
386 } | |
387 return false; | |
388 } | |
389 | |
390 public int length(){ | |
391 return count(); | |
392 } | |
393 | |
394 public int compareTo(Object o){ | |
395 IPersistentVector v = (IPersistentVector) o; | |
396 if(count() < v.count()) | |
397 return -1; | |
398 else if(count() > v.count()) | |
399 return 1; | |
400 for(int i = 0; i < count(); i++) | |
401 { | |
402 int c = Util.compare(nth(i),v.nth(i)); | |
403 if(c != 0) | |
404 return c; | |
405 } | |
406 return 0; | |
407 } | |
408 | |
409 static class Seq extends ASeq implements IndexedSeq, IReduce{ | |
410 //todo - something more efficient | |
411 final IPersistentVector v; | |
412 final int i; | |
413 | |
414 | |
415 public Seq(IPersistentVector v, int i){ | |
416 this.v = v; | |
417 this.i = i; | |
418 } | |
419 | |
420 Seq(IPersistentMap meta, IPersistentVector v, int i){ | |
421 super(meta); | |
422 this.v = v; | |
423 this.i = i; | |
424 } | |
425 | |
426 public Object first(){ | |
427 return v.nth(i); | |
428 } | |
429 | |
430 public ISeq next(){ | |
431 if(i + 1 < v.count()) | |
432 return new APersistentVector.Seq(v, i + 1); | |
433 return null; | |
434 } | |
435 | |
436 public int index(){ | |
437 return i; | |
438 } | |
439 | |
440 public int count(){ | |
441 return v.count() - i; | |
442 } | |
443 | |
444 public APersistentVector.Seq withMeta(IPersistentMap meta){ | |
445 return new APersistentVector.Seq(meta, v, i); | |
446 } | |
447 | |
448 public Object reduce(IFn f) throws Exception{ | |
449 Object ret = v.nth(i); | |
450 for(int x = i + 1; x < v.count(); x++) | |
451 ret = f.invoke(ret, v.nth(x)); | |
452 return ret; | |
453 } | |
454 | |
455 public Object reduce(IFn f, Object start) throws Exception{ | |
456 Object ret = f.invoke(start, v.nth(i)); | |
457 for(int x = i + 1; x < v.count(); x++) | |
458 ret = f.invoke(ret, v.nth(x)); | |
459 return ret; | |
460 } | |
461 } | |
462 | |
463 public static class RSeq extends ASeq implements IndexedSeq, Counted{ | |
464 final IPersistentVector v; | |
465 final int i; | |
466 | |
467 public RSeq(IPersistentVector vector, int i){ | |
468 this.v = vector; | |
469 this.i = i; | |
470 } | |
471 | |
472 RSeq(IPersistentMap meta, IPersistentVector v, int i){ | |
473 super(meta); | |
474 this.v = v; | |
475 this.i = i; | |
476 } | |
477 | |
478 public Object first(){ | |
479 return v.nth(i); | |
480 } | |
481 | |
482 public ISeq next(){ | |
483 if(i > 0) | |
484 return new APersistentVector.RSeq(v, i - 1); | |
485 return null; | |
486 } | |
487 | |
488 public int index(){ | |
489 return i; | |
490 } | |
491 | |
492 public int count(){ | |
493 return i + 1; | |
494 } | |
495 | |
496 public APersistentVector.RSeq withMeta(IPersistentMap meta){ | |
497 return new APersistentVector.RSeq(meta, v, i); | |
498 } | |
499 } | |
500 | |
501 static class SubVector extends APersistentVector implements IObj{ | |
502 final IPersistentVector v; | |
503 final int start; | |
504 final int end; | |
505 final IPersistentMap _meta; | |
506 | |
507 | |
508 | |
509 public SubVector(IPersistentMap meta, IPersistentVector v, int start, int end){ | |
510 this._meta = meta; | |
511 | |
512 if(v instanceof APersistentVector.SubVector) | |
513 { | |
514 APersistentVector.SubVector sv = (APersistentVector.SubVector) v; | |
515 start += sv.start; | |
516 end += sv.start; | |
517 v = sv.v; | |
518 } | |
519 this.v = v; | |
520 this.start = start; | |
521 this.end = end; | |
522 } | |
523 | |
524 public Object nth(int i){ | |
525 if(start + i >= end) | |
526 throw new IndexOutOfBoundsException(); | |
527 return v.nth(start + i); | |
528 } | |
529 | |
530 public IPersistentVector assocN(int i, Object val){ | |
531 if(start + i > end) | |
532 throw new IndexOutOfBoundsException(); | |
533 else if(start + i == end) | |
534 return cons(val); | |
535 return new SubVector(_meta, v.assocN(start + i, val), start, end); | |
536 } | |
537 | |
538 public int count(){ | |
539 return end - start; | |
540 } | |
541 | |
542 public IPersistentVector cons(Object o){ | |
543 return new SubVector(_meta, v.assocN(end, o), start, end + 1); | |
544 } | |
545 | |
546 public IPersistentCollection empty(){ | |
547 return PersistentVector.EMPTY.withMeta(meta()); | |
548 } | |
549 | |
550 public IPersistentStack pop(){ | |
551 if(end - 1 == start) | |
552 { | |
553 return PersistentVector.EMPTY; | |
554 } | |
555 return new SubVector(_meta, v, start, end - 1); | |
556 } | |
557 | |
558 public SubVector withMeta(IPersistentMap meta){ | |
559 if(meta == _meta) | |
560 return this; | |
561 return new SubVector(meta, v, start, end); | |
562 } | |
563 | |
564 public IPersistentMap meta(){ | |
565 return _meta; | |
566 } | |
567 } | |
568 } |