@@ -2,7 +2,6 @@ package strawman.collections
2
2
3
3
import Predef .{augmentString => _ , wrapString => _ , _ }
4
4
import scala .reflect .ClassTag
5
- import collection .mutable .ListBuffer
6
5
7
6
/** A strawman architecture for new collections. It contains some
8
7
* example collection classes and methods with the intent to expose
@@ -36,11 +35,11 @@ object CollectionStrawMan1 {
36
35
}
37
36
38
37
/** Base trait for generic collections */
39
- trait Iterable [+ IA ] extends HasIterator [IA ] with FromIterator [Iterable ]
38
+ trait Iterable [+ A ] extends HasIterator [A ] with FromIterator [Iterable ]
40
39
41
40
/** Base trait for sequence collections */
42
- trait Seq [+ AA ] extends Iterable [AA ] with FromIterator [Seq ] {
43
- def apply (i : Int ): AA
41
+ trait Seq [+ A ] extends Iterable [A ] with FromIterator [Seq ] {
42
+ def apply (i : Int ): A
44
43
def length : Int
45
44
}
46
45
@@ -53,6 +52,7 @@ object CollectionStrawMan1 {
53
52
def foldLeft [B ](z : B )(op : (B , A ) => B ): B = iterator.foldLeft(z)(op)
54
53
def foldRight [B ](z : B )(op : (A , B ) => B ): B = iterator.foldRight(z)(op)
55
54
def indexWhere (p : A => Boolean ): Int = iterator.indexWhere(p)
55
+ def isEmpty : Boolean = ! iterator.hasNext
56
56
def head : A = iterator.next
57
57
def view : View [A ] = new View (iterator)
58
58
def collect [C [X ] <: Iterable [X ]](fi : FromIterator [C ]): C [A ] = fi.fromIterator(iterator)
@@ -134,7 +134,13 @@ object CollectionStrawMan1 {
134
134
def tail = xs
135
135
}
136
136
137
- case object List extends IterableFactory [List ] {
137
+ case object Nil extends List [Nothing ] {
138
+ def isEmpty = true
139
+ def head = ???
140
+ def tail = ???
141
+ }
142
+
143
+ object List extends IterableFactory [List ] {
138
144
def fromIterator [B ](it : Iterator [B ]): List [B ] = it match {
139
145
case it : ListIterator [B ] => it.toList
140
146
case _ => if (it.hasNext) Cons (it.next, fromIterator(it)) else Nil
@@ -148,50 +154,62 @@ object CollectionStrawMan1 {
148
154
def toList = current
149
155
}
150
156
151
- case object Nil extends List [Nothing ] {
152
- def isEmpty = true
153
- def head = ???
154
- def tail = ???
155
- }
156
-
157
157
/** Concrete collection type: ArrayBuffer */
158
- class ArrayBuffer [A ] private (initElems : Array [AnyRef ], initLen : Int = 0 ) extends Seq [A ] with FromIterator [ArrayBuffer ] {
159
- def this () = this (new Array [AnyRef ](16 ))
158
+ class ArrayBuffer [A ] private (initElems : Array [AnyRef ], initLength : Int ) extends Seq [A ] with FromIterator [ArrayBuffer ] {
159
+ def this () = this (new Array [AnyRef ](16 ), 0 )
160
160
private var elems : Array [AnyRef ] = initElems
161
- private var len = 0
162
- def apply (i : Int ) = elems(i).asInstanceOf [A ]
163
- def length = len
164
- def iterator = new RandomAccessIterator [A ] {
165
- override val knownLength = len
166
- def apply (n : Int ) = elems(n).asInstanceOf [A ]
167
- }
161
+ private var start = 0
162
+ private var limit = initLength
163
+ def apply (i : Int ) = elems(start + i).asInstanceOf [A ]
164
+ def length = limit - start
165
+ def iterator = new ArrayBufferIterator [A ](elems, start, length)
168
166
def fromIterator [B ](it : Iterator [B ]): ArrayBuffer [B ] =
169
167
ArrayBuffer .fromIterator(it)
170
168
def += (elem : A ): this .type = {
171
- if (len == elems.length) {
172
- val newelems = new Array [AnyRef ](len * 2 )
173
- Array .copy(elems, 0 , newelems, 0 , len)
174
- elems = newelems
169
+ if (limit == elems.length) {
170
+ if (start > 0 ) {
171
+ Array .copy(elems, start, elems, 0 , length)
172
+ limit -= start
173
+ start = 0
174
+ }
175
+ else {
176
+ val newelems = new Array [AnyRef ](limit * 2 )
177
+ Array .copy(elems, 0 , newelems, 0 , limit)
178
+ elems = newelems
179
+ }
175
180
}
176
- elems(len ) = elem.asInstanceOf [AnyRef ]
177
- len += 1
181
+ elems(limit ) = elem.asInstanceOf [AnyRef ]
182
+ limit += 1
178
183
this
179
184
}
180
- override def toString = elems.take(len).deep.toString
185
+ def trimStart (n : Int ): Unit = start += (n max 0 )
186
+ override def toString = s " ArrayBuffer( ${elems.slice(start, limit).mkString(" , " )}) "
181
187
}
182
188
183
189
object ArrayBuffer extends IterableFactory [ArrayBuffer ] {
184
- def fromIterator [B ](it : Iterator [B ]): ArrayBuffer [B ] =
185
- if (it.knownLength == 0 ) {
186
- val elems = new Array [AnyRef ](it.knownLength)
190
+ def fromIterator [B ](it : Iterator [B ]): ArrayBuffer [B ] = it match {
191
+ case Iterator .Concat (fst : ArrayBufferIterator [_], snd : ArrayBufferIterator [_]) =>
192
+ val elems = new Array [AnyRef ](fst.remaining + snd.remaining)
193
+ Array .copy(fst.elems, fst.start, elems, 0 , fst.remaining)
194
+ Array .copy(snd.elems, snd.start, elems, fst.remaining, snd.remaining)
195
+ new ArrayBuffer (elems, elems.length)
196
+ case it @ Iterator .Partition (underlying, _, buf, _) =>
197
+ while (underlying.hasNext) it.distribute()
198
+ buf.asInstanceOf [ArrayBuffer [B ]]
199
+ case it if it.remaining >= 0 =>
200
+ val elems = new Array [AnyRef ](it.remaining)
187
201
for (i <- 0 until elems.length) elems(i) = it.next.asInstanceOf [AnyRef ]
188
- new ArrayBuffer (elems)
189
- }
190
- else {
202
+ new ArrayBuffer [B ](elems, elems.length)
203
+ case _ =>
191
204
val buf = new ArrayBuffer [B ]
192
205
while (it.hasNext) buf += it.next
193
206
buf
194
- }
207
+ }
208
+ }
209
+
210
+ class ArrayBufferIterator [A ](val elems : Array [AnyRef ], initStart : Int , length : Int ) extends RandomAccessIterator [A ] {
211
+ val limit = length
212
+ def apply (n : Int ) = elems(initStart + n).asInstanceOf [A ]
195
213
}
196
214
197
215
/** Concrete collection type: View */
@@ -219,7 +237,7 @@ object CollectionStrawMan1 {
219
237
/** Concrete collection type: String */
220
238
implicit class StringOps (val s : String ) extends AnyVal with Ops [Char ] {
221
239
def iterator : Iterator [Char ] = new RandomAccessIterator [Char ] {
222
- override val knownLength = s.length
240
+ override val limit = s.length
223
241
def apply (n : Int ) = s.charAt(n)
224
242
}
225
243
}
@@ -281,7 +299,7 @@ object CollectionStrawMan1 {
281
299
def flatMap [B ](f : A => CanIterate [B ]): Iterator [B ] = Iterator .FlatMap (this , f)
282
300
def ++ [B >: A ](xs : CanIterate [B ]): Iterator [B ] = Iterator .Concat (this , xs.iterator)
283
301
def partition (p : A => Boolean ): (Iterator [A ], Iterator [A ]) = {
284
- val lookaheadTrue, lookaheadFalse = new ListBuffer [A ]
302
+ val lookaheadTrue, lookaheadFalse = new ArrayBuffer [A ]
285
303
(Iterator .Partition (this , p, lookaheadTrue, lookaheadFalse),
286
304
Iterator .Partition [A ](this , ! p(_), lookaheadFalse, lookaheadTrue))
287
305
}
@@ -292,26 +310,34 @@ object CollectionStrawMan1 {
292
310
while (hasNext) elems = Cons (next, elems)
293
311
elems.iterator
294
312
}
313
+
314
+ /** If this iterator results from applying a transfomation to another iterator,
315
+ * that other iterator, otherwise the iterator itself.
316
+ */
295
317
def underlying : Iterator [_] = this
296
- def knownLength = - 1
318
+
319
+ /** If the number of elements still to be returned by this iterator is known,
320
+ * that number, otherwise -1.
321
+ */
322
+ def remaining = - 1
297
323
}
298
324
299
325
object Iterator {
300
326
val empty : Iterator [Nothing ] = new Iterator [Nothing ] {
301
327
def hasNext = false
302
328
def next = ???
303
- override val knownLength = 0
329
+ override def remaining = 0
304
330
}
305
331
def apply [A ](xs : A * ): Iterator [A ] = new RandomAccessIterator [A ] {
306
- override val knownLength = xs.length
332
+ override val limit = xs.length
307
333
def apply (n : Int ) = xs(n)
308
334
}
309
335
def nextOnEmpty = throw new NoSuchElementException (" next on empty iterator" )
310
336
311
337
case class Map [A , B ](override val underlying : Iterator [A ], f : A => B ) extends Iterator [B ] {
312
338
def hasNext = underlying.hasNext
313
339
def next = f(underlying.next)
314
- override val knownLength = underlying.knownLength
340
+ override def remaining = underlying.remaining
315
341
}
316
342
case class FlatMap [A , B ](override val underlying : Iterator [A ], f : A => CanIterate [B ]) extends Iterator [B ] {
317
343
private var myCurrent : Iterator [B ] = Iterator .empty
@@ -331,19 +357,18 @@ object CollectionStrawMan1 {
331
357
}
332
358
def hasNext = current.hasNext
333
359
def next = current.next
334
- override val knownLength =
335
- if (underlying.knownLength > 0 && other.knownLength > 0 )
336
- underlying.knownLength + other.knownLength
360
+ override def remaining =
361
+ if (underlying.remaining >= 0 && other.remaining >= 0 )
362
+ underlying.remaining + other.remaining
337
363
else - 1
338
364
}
339
- case class Partition [A ](override val underlying : Iterator [A ], p : A => Boolean , lookahead : ListBuffer [A ], dual : ListBuffer [A ]) extends Iterator [A ] {
365
+ case class Partition [A ](override val underlying : Iterator [A ], p : A => Boolean , lookahead : ArrayBuffer [A ], dual : ArrayBuffer [A ]) extends Iterator [A ] {
366
+ def distribute () = {
367
+ val elem = underlying.next
368
+ (if (p(elem)) lookahead else dual) += elem
369
+ }
340
370
final def hasNext : Boolean =
341
- lookahead.nonEmpty ||
342
- underlying.hasNext && {
343
- val elem = underlying.next
344
- (if (p(elem)) lookahead else dual) += elem
345
- hasNext
346
- }
371
+ ! lookahead.isEmpty || underlying.hasNext && { distribute(); hasNext }
347
372
final def next =
348
373
if (hasNext) {
349
374
val r = lookahead.head
@@ -356,27 +381,27 @@ object CollectionStrawMan1 {
356
381
def hasNext : Boolean = underlying.hasNext && (
357
382
toSkip == 0 || { underlying.next; toSkip -= 1 ; hasNext })
358
383
def next = if (hasNext) underlying.next else nextOnEmpty
359
- override val knownLength = (underlying.knownLength - n ) max - 1
384
+ override def remaining = (underlying.remaining - toSkip ) max - 1
360
385
}
361
386
case class Zip [A , B ](override val underlying : Iterator [A ], other : Iterator [B ]) extends Iterator [(A , B )] {
362
387
def hasNext = underlying.hasNext && other.hasNext
363
388
def next = (underlying.next, other.next)
364
- override val knownLength = underlying.knownLength min other.knownLength
389
+ override def remaining = underlying.remaining min other.remaining
365
390
}
366
- class Reverse [A ](underlying : RandomAccessIterator [A ]) extends RandomAccessIterator [A ] {
367
- override val knownLength = underlying.knownLength
368
- def apply ( n : Int ) = underlying.apply(knownLength - 1 - n)
391
+ case class Reverse [A ](override val underlying : RandomAccessIterator [A ]) extends RandomAccessIterator [A ] {
392
+ def apply ( n : Int ) = underlying.apply(underlying.limit - 1 - n)
393
+ def limit = underlying.remaining
369
394
}
370
395
}
371
396
372
397
trait RandomAccessIterator [+ A ] extends Iterator [A ] { self =>
373
398
def apply (n : Int ): A
374
- def knownLength : Int
375
- def length : Int = knownLength
376
- private var cur = 0
377
- def hasNext = cur < knownLength
378
- def next : A = { val r = this (cur ); cur += 1 ; r }
379
- override def drop (n : Int ): Iterator [A ] = { cur += (n max 0 ); this }
399
+ def limit : Int
400
+ var start = 0
401
+ override def remaining = (limit - start) max 0
402
+ def hasNext = start < limit
403
+ def next : A = { val r = this (start ); start += 1 ; r }
404
+ override def drop (n : Int ): Iterator [A ] = { start += (n max 0 ); this }
380
405
override def reverse : Iterator [A ] = new Iterator .Reverse (this )
381
406
}
382
407
}
0 commit comments