view src/clojure/lang/APersistentMap.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 package clojure.lang;
13 import java.io.Serializable;
14 import java.util.*;
16 public abstract class APersistentMap extends AFn implements IPersistentMap, Map, Iterable, Serializable, MapEquivalence {
17 int _hash = -1;
19 public String toString(){
20 return RT.printString(this);
21 }
23 public IPersistentCollection cons(Object o){
24 if(o instanceof Map.Entry)
25 {
26 Map.Entry e = (Map.Entry) o;
28 return assoc(e.getKey(), e.getValue());
29 }
30 else if(o instanceof IPersistentVector)
31 {
32 IPersistentVector v = (IPersistentVector) o;
33 if(v.count() != 2)
34 throw new IllegalArgumentException("Vector arg to map conj must be a pair");
35 return assoc(v.nth(0), v.nth(1));
36 }
38 IPersistentMap ret = this;
39 for(ISeq es = RT.seq(o); es != null; es = es.next())
40 {
41 Map.Entry e = (Map.Entry) es.first();
42 ret = ret.assoc(e.getKey(), e.getValue());
43 }
44 return ret;
45 }
47 public boolean equals(Object obj){
48 return mapEquals(this, obj);
49 }
51 static public boolean mapEquals(IPersistentMap m1, Object obj){
52 if(m1 == obj) return true;
53 if(!(obj instanceof Map))
54 return false;
55 Map m = (Map) obj;
57 if(m.size() != m1.count() || m.hashCode() != m1.hashCode())
58 return false;
60 for(ISeq s = m1.seq(); s != null; s = s.next())
61 {
62 Map.Entry e = (Map.Entry) s.first();
63 boolean found = m.containsKey(e.getKey());
65 if(!found || !Util.equals(e.getValue(), m.get(e.getKey())))
66 return false;
67 }
69 return true;
70 }
72 public boolean equiv(Object obj){
73 if(!(obj instanceof Map))
74 return false;
75 if(obj instanceof IPersistentMap && !(obj instanceof MapEquivalence))
76 return false;
78 Map m = (Map) obj;
80 if(m.size() != size())
81 return false;
83 for(ISeq s = seq(); s != null; s = s.next())
84 {
85 Map.Entry e = (Map.Entry) s.first();
86 boolean found = m.containsKey(e.getKey());
88 if(!found || !Util.equiv(e.getValue(), m.get(e.getKey())))
89 return false;
90 }
92 return true;
93 }
94 public int hashCode(){
95 if(_hash == -1)
96 {
97 this._hash = mapHash(this);
98 }
99 return _hash;
100 }
102 static public int mapHash(IPersistentMap m){
103 int hash = 0;
104 for(ISeq s = m.seq(); s != null; s = s.next())
105 {
106 Map.Entry e = (Map.Entry) s.first();
107 hash += (e.getKey() == null ? 0 : e.getKey().hashCode()) ^
108 (e.getValue() == null ? 0 : e.getValue().hashCode());
109 }
110 return hash;
111 }
113 static public class KeySeq extends ASeq{
114 ISeq seq;
116 static public KeySeq create(ISeq seq){
117 if(seq == null)
118 return null;
119 return new KeySeq(seq);
120 }
122 private KeySeq(ISeq seq){
123 this.seq = seq;
124 }
126 private KeySeq(IPersistentMap meta, ISeq seq){
127 super(meta);
128 this.seq = seq;
129 }
131 public Object first(){
132 return ((Map.Entry) seq.first()).getKey();
133 }
135 public ISeq next(){
136 return create(seq.next());
137 }
139 public KeySeq withMeta(IPersistentMap meta){
140 return new KeySeq(meta, seq);
141 }
142 }
144 static public class ValSeq extends ASeq{
145 ISeq seq;
147 static public ValSeq create(ISeq seq){
148 if(seq == null)
149 return null;
150 return new ValSeq(seq);
151 }
153 private ValSeq(ISeq seq){
154 this.seq = seq;
155 }
157 private ValSeq(IPersistentMap meta, ISeq seq){
158 super(meta);
159 this.seq = seq;
160 }
162 public Object first(){
163 return ((Map.Entry) seq.first()).getValue();
164 }
166 public ISeq next(){
167 return create(seq.next());
168 }
170 public ValSeq withMeta(IPersistentMap meta){
171 return new ValSeq(meta, seq);
172 }
173 }
176 public Object invoke(Object arg1) throws Exception{
177 return valAt(arg1);
178 }
180 public Object invoke(Object arg1, Object notFound) throws Exception{
181 return valAt(arg1, notFound);
182 }
184 // java.util.Map implementation
186 public void clear(){
187 throw new UnsupportedOperationException();
188 }
190 public boolean containsValue(Object value){
191 return values().contains(value);
192 }
194 public Set entrySet(){
195 return new AbstractSet(){
197 public Iterator iterator(){
198 return APersistentMap.this.iterator();
199 }
201 public int size(){
202 return count();
203 }
205 public int hashCode(){
206 return APersistentMap.this.hashCode();
207 }
209 public boolean contains(Object o){
210 if(o instanceof Entry)
211 {
212 Entry e = (Entry) o;
213 Entry found = entryAt(e.getKey());
214 if(found != null && Util.equals(found.getValue(), e.getValue()))
215 return true;
216 }
217 return false;
218 }
219 };
220 }
222 public Object get(Object key){
223 return valAt(key);
224 }
226 public boolean isEmpty(){
227 return count() == 0;
228 }
230 public Set keySet(){
231 return new AbstractSet(){
233 public Iterator iterator(){
234 final Iterator mi = APersistentMap.this.iterator();
236 return new Iterator(){
239 public boolean hasNext(){
240 return mi.hasNext();
241 }
243 public Object next(){
244 Entry e = (Entry) mi.next();
245 return e.getKey();
246 }
248 public void remove(){
249 throw new UnsupportedOperationException();
250 }
251 };
252 }
254 public int size(){
255 return count();
256 }
258 public boolean contains(Object o){
259 return APersistentMap.this.containsKey(o);
260 }
261 };
262 }
264 public Object put(Object key, Object value){
265 throw new UnsupportedOperationException();
266 }
268 public void putAll(Map t){
269 throw new UnsupportedOperationException();
270 }
272 public Object remove(Object key){
273 throw new UnsupportedOperationException();
274 }
276 public int size(){
277 return count();
278 }
280 public Collection values(){
281 return new AbstractCollection(){
283 public Iterator iterator(){
284 final Iterator mi = APersistentMap.this.iterator();
286 return new Iterator(){
289 public boolean hasNext(){
290 return mi.hasNext();
291 }
293 public Object next(){
294 Entry e = (Entry) mi.next();
295 return e.getValue();
296 }
298 public void remove(){
299 throw new UnsupportedOperationException();
300 }
301 };
302 }
304 public int size(){
305 return count();
306 }
307 };
308 }
310 /*
311 // java.util.Collection implementation
313 public Object[] toArray(){
314 return RT.seqToArray(seq());
315 }
317 public boolean add(Object o){
318 throw new UnsupportedOperationException();
319 }
321 public boolean remove(Object o){
322 throw new UnsupportedOperationException();
323 }
325 public boolean addAll(Collection c){
326 throw new UnsupportedOperationException();
327 }
329 public void clear(){
330 throw new UnsupportedOperationException();
331 }
333 public boolean retainAll(Collection c){
334 throw new UnsupportedOperationException();
335 }
337 public boolean removeAll(Collection c){
338 throw new UnsupportedOperationException();
339 }
341 public boolean containsAll(Collection c){
342 for(Object o : c)
343 {
344 if(!contains(o))
345 return false;
346 }
347 return true;
348 }
350 public Object[] toArray(Object[] a){
351 if(a.length >= count())
352 {
353 ISeq s = seq();
354 for(int i = 0; s != null; ++i, s = s.rest())
355 {
356 a[i] = s.first();
357 }
358 if(a.length > count())
359 a[count()] = null;
360 return a;
361 }
362 else
363 return toArray();
364 }
366 public int size(){
367 return count();
368 }
370 public boolean isEmpty(){
371 return count() == 0;
372 }
374 public boolean contains(Object o){
375 if(o instanceof Map.Entry)
376 {
377 Map.Entry e = (Map.Entry) o;
378 Map.Entry v = entryAt(e.getKey());
379 return (v != null && Util.equal(v.getValue(), e.getValue()));
380 }
381 return false;
382 }
383 */
384 }