Mercurial > lasercutter
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 the4 * 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 by7 * 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 else67 {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 else110 {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 efficient255 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 implementation320 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 else370 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 efficient411 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 }