Mercurial > lasercutter
comparison 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 |
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 package clojure.lang; | |
12 | |
13 import java.io.Serializable; | |
14 import java.util.*; | |
15 | |
16 public abstract class APersistentMap extends AFn implements IPersistentMap, Map, Iterable, Serializable, MapEquivalence { | |
17 int _hash = -1; | |
18 | |
19 public String toString(){ | |
20 return RT.printString(this); | |
21 } | |
22 | |
23 public IPersistentCollection cons(Object o){ | |
24 if(o instanceof Map.Entry) | |
25 { | |
26 Map.Entry e = (Map.Entry) o; | |
27 | |
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 } | |
37 | |
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 } | |
46 | |
47 public boolean equals(Object obj){ | |
48 return mapEquals(this, obj); | |
49 } | |
50 | |
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; | |
56 | |
57 if(m.size() != m1.count() || m.hashCode() != m1.hashCode()) | |
58 return false; | |
59 | |
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()); | |
64 | |
65 if(!found || !Util.equals(e.getValue(), m.get(e.getKey()))) | |
66 return false; | |
67 } | |
68 | |
69 return true; | |
70 } | |
71 | |
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; | |
77 | |
78 Map m = (Map) obj; | |
79 | |
80 if(m.size() != size()) | |
81 return false; | |
82 | |
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()); | |
87 | |
88 if(!found || !Util.equiv(e.getValue(), m.get(e.getKey()))) | |
89 return false; | |
90 } | |
91 | |
92 return true; | |
93 } | |
94 public int hashCode(){ | |
95 if(_hash == -1) | |
96 { | |
97 this._hash = mapHash(this); | |
98 } | |
99 return _hash; | |
100 } | |
101 | |
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 } | |
112 | |
113 static public class KeySeq extends ASeq{ | |
114 ISeq seq; | |
115 | |
116 static public KeySeq create(ISeq seq){ | |
117 if(seq == null) | |
118 return null; | |
119 return new KeySeq(seq); | |
120 } | |
121 | |
122 private KeySeq(ISeq seq){ | |
123 this.seq = seq; | |
124 } | |
125 | |
126 private KeySeq(IPersistentMap meta, ISeq seq){ | |
127 super(meta); | |
128 this.seq = seq; | |
129 } | |
130 | |
131 public Object first(){ | |
132 return ((Map.Entry) seq.first()).getKey(); | |
133 } | |
134 | |
135 public ISeq next(){ | |
136 return create(seq.next()); | |
137 } | |
138 | |
139 public KeySeq withMeta(IPersistentMap meta){ | |
140 return new KeySeq(meta, seq); | |
141 } | |
142 } | |
143 | |
144 static public class ValSeq extends ASeq{ | |
145 ISeq seq; | |
146 | |
147 static public ValSeq create(ISeq seq){ | |
148 if(seq == null) | |
149 return null; | |
150 return new ValSeq(seq); | |
151 } | |
152 | |
153 private ValSeq(ISeq seq){ | |
154 this.seq = seq; | |
155 } | |
156 | |
157 private ValSeq(IPersistentMap meta, ISeq seq){ | |
158 super(meta); | |
159 this.seq = seq; | |
160 } | |
161 | |
162 public Object first(){ | |
163 return ((Map.Entry) seq.first()).getValue(); | |
164 } | |
165 | |
166 public ISeq next(){ | |
167 return create(seq.next()); | |
168 } | |
169 | |
170 public ValSeq withMeta(IPersistentMap meta){ | |
171 return new ValSeq(meta, seq); | |
172 } | |
173 } | |
174 | |
175 | |
176 public Object invoke(Object arg1) throws Exception{ | |
177 return valAt(arg1); | |
178 } | |
179 | |
180 public Object invoke(Object arg1, Object notFound) throws Exception{ | |
181 return valAt(arg1, notFound); | |
182 } | |
183 | |
184 // java.util.Map implementation | |
185 | |
186 public void clear(){ | |
187 throw new UnsupportedOperationException(); | |
188 } | |
189 | |
190 public boolean containsValue(Object value){ | |
191 return values().contains(value); | |
192 } | |
193 | |
194 public Set entrySet(){ | |
195 return new AbstractSet(){ | |
196 | |
197 public Iterator iterator(){ | |
198 return APersistentMap.this.iterator(); | |
199 } | |
200 | |
201 public int size(){ | |
202 return count(); | |
203 } | |
204 | |
205 public int hashCode(){ | |
206 return APersistentMap.this.hashCode(); | |
207 } | |
208 | |
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 } | |
221 | |
222 public Object get(Object key){ | |
223 return valAt(key); | |
224 } | |
225 | |
226 public boolean isEmpty(){ | |
227 return count() == 0; | |
228 } | |
229 | |
230 public Set keySet(){ | |
231 return new AbstractSet(){ | |
232 | |
233 public Iterator iterator(){ | |
234 final Iterator mi = APersistentMap.this.iterator(); | |
235 | |
236 return new Iterator(){ | |
237 | |
238 | |
239 public boolean hasNext(){ | |
240 return mi.hasNext(); | |
241 } | |
242 | |
243 public Object next(){ | |
244 Entry e = (Entry) mi.next(); | |
245 return e.getKey(); | |
246 } | |
247 | |
248 public void remove(){ | |
249 throw new UnsupportedOperationException(); | |
250 } | |
251 }; | |
252 } | |
253 | |
254 public int size(){ | |
255 return count(); | |
256 } | |
257 | |
258 public boolean contains(Object o){ | |
259 return APersistentMap.this.containsKey(o); | |
260 } | |
261 }; | |
262 } | |
263 | |
264 public Object put(Object key, Object value){ | |
265 throw new UnsupportedOperationException(); | |
266 } | |
267 | |
268 public void putAll(Map t){ | |
269 throw new UnsupportedOperationException(); | |
270 } | |
271 | |
272 public Object remove(Object key){ | |
273 throw new UnsupportedOperationException(); | |
274 } | |
275 | |
276 public int size(){ | |
277 return count(); | |
278 } | |
279 | |
280 public Collection values(){ | |
281 return new AbstractCollection(){ | |
282 | |
283 public Iterator iterator(){ | |
284 final Iterator mi = APersistentMap.this.iterator(); | |
285 | |
286 return new Iterator(){ | |
287 | |
288 | |
289 public boolean hasNext(){ | |
290 return mi.hasNext(); | |
291 } | |
292 | |
293 public Object next(){ | |
294 Entry e = (Entry) mi.next(); | |
295 return e.getValue(); | |
296 } | |
297 | |
298 public void remove(){ | |
299 throw new UnsupportedOperationException(); | |
300 } | |
301 }; | |
302 } | |
303 | |
304 public int size(){ | |
305 return count(); | |
306 } | |
307 }; | |
308 } | |
309 | |
310 /* | |
311 // java.util.Collection implementation | |
312 | |
313 public Object[] toArray(){ | |
314 return RT.seqToArray(seq()); | |
315 } | |
316 | |
317 public boolean add(Object o){ | |
318 throw new UnsupportedOperationException(); | |
319 } | |
320 | |
321 public boolean remove(Object o){ | |
322 throw new UnsupportedOperationException(); | |
323 } | |
324 | |
325 public boolean addAll(Collection c){ | |
326 throw new UnsupportedOperationException(); | |
327 } | |
328 | |
329 public void clear(){ | |
330 throw new UnsupportedOperationException(); | |
331 } | |
332 | |
333 public boolean retainAll(Collection c){ | |
334 throw new UnsupportedOperationException(); | |
335 } | |
336 | |
337 public boolean removeAll(Collection c){ | |
338 throw new UnsupportedOperationException(); | |
339 } | |
340 | |
341 public boolean containsAll(Collection c){ | |
342 for(Object o : c) | |
343 { | |
344 if(!contains(o)) | |
345 return false; | |
346 } | |
347 return true; | |
348 } | |
349 | |
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 } | |
365 | |
366 public int size(){ | |
367 return count(); | |
368 } | |
369 | |
370 public boolean isEmpty(){ | |
371 return count() == 0; | |
372 } | |
373 | |
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 } |