view src/clojure/lang/PersistentQueue.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.util.Collection;
14 import java.util.Iterator;
15 //import java.util.concurrent.ConcurrentLinkedQueue;
17 /**
18 * conses onto rear, peeks/pops from front
19 * See Okasaki's Batched Queues
20 * This differs in that it uses a PersistentArrayList as the rear, which is in-order,
21 * so no reversing or suspensions required for persistent use
22 */
24 public class PersistentQueue extends Obj implements IPersistentList, Collection{
26 final public static PersistentQueue EMPTY = new PersistentQueue(null, null, null);
28 //*
29 final ISeq f;
30 final PersistentVector r;
31 //static final int INITIAL_REAR_SIZE = 4;
32 int _hash = -1;
34 PersistentQueue(IPersistentMap meta, ISeq f, PersistentVector r){
35 super(meta);
36 this.f = f;
37 this.r = r;
38 }
40 public boolean equiv(Object obj){
42 if(!(obj instanceof Sequential))
43 return false;
44 ISeq ms = RT.seq(obj);
45 for(ISeq s = seq(); s != null; s = s.next(), ms = ms.next())
46 {
47 if(ms == null || !Util.equiv(s.first(), ms.first()))
48 return false;
49 }
50 return ms == null;
52 }
54 public boolean equals(Object obj){
56 if(!(obj instanceof Sequential))
57 return false;
58 ISeq ms = RT.seq(obj);
59 for(ISeq s = seq(); s != null; s = s.next(), ms = ms.next())
60 {
61 if(ms == null || !Util.equals(s.first(), ms.first()))
62 return false;
63 }
64 return ms == null;
66 }
68 public int hashCode(){
69 if(_hash == -1)
70 {
71 int hash = 0;
72 for(ISeq s = seq(); s != null; s = s.next())
73 {
74 hash = Util.hashCombine(hash, Util.hash(s.first()));
75 }
76 this._hash = hash;
77 }
78 return _hash;
79 }
81 public Object peek(){
82 return RT.first(f);
83 }
85 public PersistentQueue pop(){
86 if(f == null) //hmmm... pop of empty queue -> empty queue?
87 return this;
88 //throw new IllegalStateException("popping empty queue");
89 ISeq f1 = f.next();
90 PersistentVector r1 = r;
91 if(f1 == null)
92 {
93 f1 = RT.seq(r);
94 r1 = null;
95 }
96 return new PersistentQueue(meta(), f1, r1);
97 }
99 public int count(){
100 return RT.count(f) + RT.count(r);
101 }
103 public ISeq seq(){
104 if(f == null)
105 return null;
106 return new Seq(f, RT.seq(r));
107 }
109 public PersistentQueue cons(Object o){
110 if(f == null) //empty
111 return new PersistentQueue(meta(), RT.list(o), null);
112 else
113 return new PersistentQueue(meta(), f, (r != null ? r : PersistentVector.EMPTY).cons(o));
114 }
116 public IPersistentCollection empty(){
117 return EMPTY.withMeta(meta());
118 }
120 public PersistentQueue withMeta(IPersistentMap meta){
121 return new PersistentQueue(meta, f, r);
122 }
124 static class Seq extends ASeq{
125 final ISeq f;
126 final ISeq rseq;
128 Seq(ISeq f, ISeq rseq){
129 this.f = f;
130 this.rseq = rseq;
131 }
133 Seq(IPersistentMap meta, ISeq f, ISeq rseq){
134 super(meta);
135 this.f = f;
136 this.rseq = rseq;
137 }
139 public Object first(){
140 return f.first();
141 }
143 public ISeq next(){
144 ISeq f1 = f.next();
145 ISeq r1 = rseq;
146 if(f1 == null)
147 {
148 if(rseq == null)
149 return null;
150 f1 = rseq;
151 r1 = null;
152 }
153 return new Seq(f1, r1);
154 }
156 public int count(){
157 return RT.count(f) + RT.count(rseq);
158 }
160 public Seq withMeta(IPersistentMap meta){
161 return new Seq(meta, f, rseq);
162 }
163 }
165 // java.util.Collection implementation
167 public Object[] toArray(){
168 return RT.seqToArray(seq());
169 }
171 public boolean add(Object o){
172 throw new UnsupportedOperationException();
173 }
175 public boolean remove(Object o){
176 throw new UnsupportedOperationException();
177 }
179 public boolean addAll(Collection c){
180 throw new UnsupportedOperationException();
181 }
183 public void clear(){
184 throw new UnsupportedOperationException();
185 }
187 public boolean retainAll(Collection c){
188 throw new UnsupportedOperationException();
189 }
191 public boolean removeAll(Collection c){
192 throw new UnsupportedOperationException();
193 }
195 public boolean containsAll(Collection c){
196 for(Object o : c)
197 {
198 if(contains(o))
199 return true;
200 }
201 return false;
202 }
204 public Object[] toArray(Object[] a){
205 if(a.length >= count())
206 {
207 ISeq s = seq();
208 for(int i = 0; s != null; ++i, s = s.next())
209 {
210 a[i] = s.first();
211 }
212 if(a.length >= count())
213 a[count()] = null;
214 return a;
215 }
216 else
217 return toArray();
218 }
220 public int size(){
221 return count();
222 }
224 public boolean isEmpty(){
225 return count() == 0;
226 }
228 public boolean contains(Object o){
229 for(ISeq s = seq(); s != null; s = s.next())
230 {
231 if(Util.equiv(s.first(), o))
232 return true;
233 }
234 return false;
235 }
237 public Iterator iterator(){
238 return new SeqIterator(seq());
239 }
241 /*
242 public static void main(String[] args){
243 if(args.length != 1)
244 {
245 System.err.println("Usage: PersistentQueue n");
246 return;
247 }
248 int n = Integer.parseInt(args[0]);
251 long startTime, estimatedTime;
253 Queue list = new LinkedList();
254 //Queue list = new ConcurrentLinkedQueue();
255 System.out.println("Queue");
256 startTime = System.nanoTime();
257 for(int i = 0; i < n; i++)
258 {
259 list.add(i);
260 list.add(i);
261 list.remove();
262 }
263 for(int i = 0; i < n - 10; i++)
264 {
265 list.remove();
266 }
267 estimatedTime = System.nanoTime() - startTime;
268 System.out.println("time: " + estimatedTime / 1000000);
269 System.out.println("peek: " + list.peek());
272 PersistentQueue q = PersistentQueue.EMPTY;
273 System.out.println("PersistentQueue");
274 startTime = System.nanoTime();
275 for(int i = 0; i < n; i++)
276 {
277 q = q.cons(i);
278 q = q.cons(i);
279 q = q.pop();
280 }
281 // IPersistentList lastq = null;
282 // IPersistentList lastq2;
283 for(int i = 0; i < n - 10; i++)
284 {
285 //lastq2 = lastq;
286 //lastq = q;
287 q = q.pop();
288 }
289 estimatedTime = System.nanoTime() - startTime;
290 System.out.println("time: " + estimatedTime / 1000000);
291 System.out.println("peek: " + q.peek());
293 IPersistentList q2 = q;
294 for(int i = 0; i < 10; i++)
295 {
296 q2 = (IPersistentList) q2.cons(i);
297 }
298 // for(ISeq s = q.seq();s != null;s = s.rest())
299 // System.out.println("q: " + s.first().toString());
300 // for(ISeq s = q2.seq();s != null;s = s.rest())
301 // System.out.println("q2: " + s.first().toString());
302 }
303 */
304 }