Skip to content

Commit 1521121

Browse files
committed
Bugfixes and move CollectionStrawMan1 into the correct directory.
1 parent 135b725 commit 1521121

File tree

2 files changed

+96
-71
lines changed

2 files changed

+96
-71
lines changed

src/dotty/collections/CollectionStrawMan1.scala renamed to src/strawman/collections/CollectionStrawMan1.scala

Lines changed: 86 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package strawman.collections
22

33
import Predef.{augmentString => _, wrapString => _, _}
44
import scala.reflect.ClassTag
5-
import collection.mutable.ListBuffer
65

76
/** A strawman architecture for new collections. It contains some
87
* example collection classes and methods with the intent to expose
@@ -36,11 +35,11 @@ object CollectionStrawMan1 {
3635
}
3736

3837
/** 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]
4039

4140
/** 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
4443
def length: Int
4544
}
4645

@@ -53,6 +52,7 @@ object CollectionStrawMan1 {
5352
def foldLeft[B](z: B)(op: (B, A) => B): B = iterator.foldLeft(z)(op)
5453
def foldRight[B](z: B)(op: (A, B) => B): B = iterator.foldRight(z)(op)
5554
def indexWhere(p: A => Boolean): Int = iterator.indexWhere(p)
55+
def isEmpty: Boolean = !iterator.hasNext
5656
def head: A = iterator.next
5757
def view: View[A] = new View(iterator)
5858
def collect[C[X] <: Iterable[X]](fi: FromIterator[C]): C[A] = fi.fromIterator(iterator)
@@ -134,7 +134,13 @@ object CollectionStrawMan1 {
134134
def tail = xs
135135
}
136136

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] {
138144
def fromIterator[B](it: Iterator[B]): List[B] = it match {
139145
case it: ListIterator[B] => it.toList
140146
case _ => if (it.hasNext) Cons(it.next, fromIterator(it)) else Nil
@@ -148,50 +154,62 @@ object CollectionStrawMan1 {
148154
def toList = current
149155
}
150156

151-
case object Nil extends List[Nothing] {
152-
def isEmpty = true
153-
def head = ???
154-
def tail = ???
155-
}
156-
157157
/** 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)
160160
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)
168166
def fromIterator[B](it: Iterator[B]): ArrayBuffer[B] =
169167
ArrayBuffer.fromIterator(it)
170168
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+
}
175180
}
176-
elems(len) = elem.asInstanceOf[AnyRef]
177-
len += 1
181+
elems(limit) = elem.asInstanceOf[AnyRef]
182+
limit += 1
178183
this
179184
}
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(", ")})"
181187
}
182188

183189
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)
187201
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 _ =>
191204
val buf = new ArrayBuffer[B]
192205
while (it.hasNext) buf += it.next
193206
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]
195213
}
196214

197215
/** Concrete collection type: View */
@@ -219,7 +237,7 @@ object CollectionStrawMan1 {
219237
/** Concrete collection type: String */
220238
implicit class StringOps(val s: String) extends AnyVal with Ops[Char] {
221239
def iterator: Iterator[Char] = new RandomAccessIterator[Char] {
222-
override val knownLength = s.length
240+
override val limit = s.length
223241
def apply(n: Int) = s.charAt(n)
224242
}
225243
}
@@ -281,7 +299,7 @@ object CollectionStrawMan1 {
281299
def flatMap[B](f: A => CanIterate[B]): Iterator[B] = Iterator.FlatMap(this, f)
282300
def ++[B >: A](xs: CanIterate[B]): Iterator[B] = Iterator.Concat(this, xs.iterator)
283301
def partition(p: A => Boolean): (Iterator[A], Iterator[A]) = {
284-
val lookaheadTrue, lookaheadFalse = new ListBuffer[A]
302+
val lookaheadTrue, lookaheadFalse = new ArrayBuffer[A]
285303
(Iterator.Partition(this, p, lookaheadTrue, lookaheadFalse),
286304
Iterator.Partition[A](this, !p(_), lookaheadFalse, lookaheadTrue))
287305
}
@@ -292,26 +310,34 @@ object CollectionStrawMan1 {
292310
while (hasNext) elems = Cons(next, elems)
293311
elems.iterator
294312
}
313+
314+
/** If this iterator results from applying a transfomation to another iterator,
315+
* that other iterator, otherwise the iterator itself.
316+
*/
295317
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
297323
}
298324

299325
object Iterator {
300326
val empty: Iterator[Nothing] = new Iterator[Nothing] {
301327
def hasNext = false
302328
def next = ???
303-
override val knownLength = 0
329+
override def remaining = 0
304330
}
305331
def apply[A](xs: A*): Iterator[A] = new RandomAccessIterator[A] {
306-
override val knownLength = xs.length
332+
override val limit = xs.length
307333
def apply(n: Int) = xs(n)
308334
}
309335
def nextOnEmpty = throw new NoSuchElementException("next on empty iterator")
310336

311337
case class Map[A, B](override val underlying: Iterator[A], f: A => B) extends Iterator[B] {
312338
def hasNext = underlying.hasNext
313339
def next = f(underlying.next)
314-
override val knownLength = underlying.knownLength
340+
override def remaining = underlying.remaining
315341
}
316342
case class FlatMap[A, B](override val underlying: Iterator[A], f: A => CanIterate[B]) extends Iterator[B] {
317343
private var myCurrent: Iterator[B] = Iterator.empty
@@ -331,19 +357,18 @@ object CollectionStrawMan1 {
331357
}
332358
def hasNext = current.hasNext
333359
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
337363
else -1
338364
}
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+
}
340370
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 }
347372
final def next =
348373
if (hasNext) {
349374
val r = lookahead.head
@@ -356,27 +381,27 @@ object CollectionStrawMan1 {
356381
def hasNext: Boolean = underlying.hasNext && (
357382
toSkip == 0 || { underlying.next; toSkip -= 1; hasNext })
358383
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
360385
}
361386
case class Zip[A, B](override val underlying: Iterator[A], other: Iterator[B]) extends Iterator[(A, B)] {
362387
def hasNext = underlying.hasNext && other.hasNext
363388
def next = (underlying.next, other.next)
364-
override val knownLength = underlying.knownLength min other.knownLength
389+
override def remaining = underlying.remaining min other.remaining
365390
}
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
369394
}
370395
}
371396

372397
trait RandomAccessIterator[+A] extends Iterator[A] { self =>
373398
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 }
380405
override def reverse: Iterator[A] = new Iterator.Reverse(this)
381406
}
382407
}

tests/run/CollectionTests.check

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,17 @@ Cons(3,Cons(2,Cons(1,Nil)))
2121
1
2222
1
2323
Cons(1,Cons(2,Cons(3,Nil)))
24-
Array(2)
25-
Array(1, 3)
26-
Array(3)
27-
Array(true, true, true)
28-
Array(1, -1, 2, -2, 3, -3)
29-
Array(1, 2, 3, 1, 2, 3)
30-
Array(1, 2, 3)
24+
ArrayBuffer(2)
25+
ArrayBuffer(1, 3)
26+
ArrayBuffer(3)
27+
ArrayBuffer(true, true, true)
28+
ArrayBuffer(1, -1, 2, -2, 3, -3)
29+
ArrayBuffer(1, 2, 3, 1, 2, 3)
30+
ArrayBuffer(1, 2, 3)
3131
Cons(1,Cons(2,Cons(3,Nil)))
32-
Array(1, 2, 3, a)
33-
Array((1,true), (2,true), (3,true))
34-
Array(3, 2, 1)
32+
ArrayBuffer(1, 2, 3, a)
33+
ArrayBuffer((1,true), (2,true), (3,true))
34+
ArrayBuffer(3, 2, 1)
3535
-------
3636
123
3737
123

0 commit comments

Comments
 (0)