view 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
line wrap: on
line source
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 **/
11 /* rich Dec 18, 2007 */
13 package clojure.lang;
15 import java.io.Serializable;
16 import java.util.*;
18 public abstract class APersistentVector extends AFn implements IPersistentVector, Iterable,
19 List,
20 RandomAccess, Comparable,
21 Serializable {
22 int _hash = -1;
24 public String toString(){
25 return RT.printString(this);
26 }
28 public ISeq seq(){
29 if(count() > 0)
30 return new Seq(this, 0);
31 return null;
32 }
34 public ISeq rseq(){
35 if(count() > 0)
36 return new RSeq(this, count() - 1);
37 return null;
38 }
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 }
80 return true;
82 }
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 }
123 return true;
125 }
127 public boolean equals(Object obj){
128 return doEquals(this, obj);
129 }
131 public boolean equiv(Object obj){
132 return doEquiv(this, obj);
133 }
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 }
155 public Object get(int index){
156 return nth(index);
157 }
159 public Object nth(int i, Object notFound){
160 if(i >= 0 && i < count())
161 return nth(i);
162 return notFound;
163 }
165 public Object remove(int i){
166 throw new UnsupportedOperationException();
167 }
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 }
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 }
183 public ListIterator listIterator(){
184 return listIterator(0);
185 }
187 public ListIterator listIterator(final int index){
188 return new ListIterator(){
189 int nexti = index;
191 public boolean hasNext(){
192 return nexti < count();
193 }
195 public Object next(){
196 return nth(nexti++);
197 }
199 public boolean hasPrevious(){
200 return nexti > 0;
201 }
203 public Object previous(){
204 return nth(--nexti);
205 }
207 public int nextIndex(){
208 return nexti;
209 }
211 public int previousIndex(){
212 return nexti - 1;
213 }
215 public void remove(){
216 throw new UnsupportedOperationException();
217 }
219 public void set(Object o){
220 throw new UnsupportedOperationException();
221 }
223 public void add(Object o){
224 throw new UnsupportedOperationException();
225 }
226 };
227 }
229 public List subList(int fromIndex, int toIndex){
230 return (List) RT.subvec(this, fromIndex, toIndex);
231 }
234 public Object set(int i, Object o){
235 throw new UnsupportedOperationException();
236 }
238 public void add(int i, Object o){
239 throw new UnsupportedOperationException();
240 }
242 public boolean addAll(int i, Collection c){
243 throw new UnsupportedOperationException();
244 }
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 }
253 public Iterator iterator(){
254 //todo - something more efficient
255 return new Iterator(){
256 int i = 0;
258 public boolean hasNext(){
259 return i < count();
260 }
262 public Object next(){
263 return nth(i++);
264 }
266 public void remove(){
267 throw new UnsupportedOperationException();
268 }
269 };
270 }
272 public Object peek(){
273 if(count() > 0)
274 return nth(count() - 1);
275 return null;
276 }
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 }
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 }
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 }
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 }
314 public Object valAt(Object key){
315 return valAt(key, null);
316 }
318 // java.util.Collection implementation
320 public Object[] toArray(){
321 return RT.seqToArray(seq());
322 }
324 public boolean add(Object o){
325 throw new UnsupportedOperationException();
326 }
328 public boolean remove(Object o){
329 throw new UnsupportedOperationException();
330 }
332 public boolean addAll(Collection c){
333 throw new UnsupportedOperationException();
334 }
336 public void clear(){
337 throw new UnsupportedOperationException();
338 }
340 public boolean retainAll(Collection c){
341 throw new UnsupportedOperationException();
342 }
344 public boolean removeAll(Collection c){
345 throw new UnsupportedOperationException();
346 }
348 public boolean containsAll(Collection c){
349 for(Object o : c)
350 {
351 if(!contains(o))
352 return false;
353 }
354 return true;
355 }
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 }
373 public int size(){
374 return count();
375 }
377 public boolean isEmpty(){
378 return count() == 0;
379 }
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 }
390 public int length(){
391 return count();
392 }
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 }
409 static class Seq extends ASeq implements IndexedSeq, IReduce{
410 //todo - something more efficient
411 final IPersistentVector v;
412 final int i;
415 public Seq(IPersistentVector v, int i){
416 this.v = v;
417 this.i = i;
418 }
420 Seq(IPersistentMap meta, IPersistentVector v, int i){
421 super(meta);
422 this.v = v;
423 this.i = i;
424 }
426 public Object first(){
427 return v.nth(i);
428 }
430 public ISeq next(){
431 if(i + 1 < v.count())
432 return new APersistentVector.Seq(v, i + 1);
433 return null;
434 }
436 public int index(){
437 return i;
438 }
440 public int count(){
441 return v.count() - i;
442 }
444 public APersistentVector.Seq withMeta(IPersistentMap meta){
445 return new APersistentVector.Seq(meta, v, i);
446 }
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 }
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 }
463 public static class RSeq extends ASeq implements IndexedSeq, Counted{
464 final IPersistentVector v;
465 final int i;
467 public RSeq(IPersistentVector vector, int i){
468 this.v = vector;
469 this.i = i;
470 }
472 RSeq(IPersistentMap meta, IPersistentVector v, int i){
473 super(meta);
474 this.v = v;
475 this.i = i;
476 }
478 public Object first(){
479 return v.nth(i);
480 }
482 public ISeq next(){
483 if(i > 0)
484 return new APersistentVector.RSeq(v, i - 1);
485 return null;
486 }
488 public int index(){
489 return i;
490 }
492 public int count(){
493 return i + 1;
494 }
496 public APersistentVector.RSeq withMeta(IPersistentMap meta){
497 return new APersistentVector.RSeq(meta, v, i);
498 }
499 }
501 static class SubVector extends APersistentVector implements IObj{
502 final IPersistentVector v;
503 final int start;
504 final int end;
505 final IPersistentMap _meta;
509 public SubVector(IPersistentMap meta, IPersistentVector v, int start, int end){
510 this._meta = meta;
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 }
524 public Object nth(int i){
525 if(start + i >= end)
526 throw new IndexOutOfBoundsException();
527 return v.nth(start + i);
528 }
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 }
538 public int count(){
539 return end - start;
540 }
542 public IPersistentVector cons(Object o){
543 return new SubVector(_meta, v.assocN(end, o), start, end + 1);
544 }
546 public IPersistentCollection empty(){
547 return PersistentVector.EMPTY.withMeta(meta());
548 }
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 }
558 public SubVector withMeta(IPersistentMap meta){
559 if(meta == _meta)
560 return this;
561 return new SubVector(meta, v, start, end);
562 }
564 public IPersistentMap meta(){
565 return _meta;
566 }
567 }
568 }