Skip to content

Commit 135b725

Browse files
committed
Add ArrayBuffer as another Seq class. Make iterators inspectable.
1 parent 868ae2a commit 135b725

File tree

3 files changed

+173
-101
lines changed

3 files changed

+173
-101
lines changed

src/dotty/collections/CollectionStrawMan1.scala

Lines changed: 154 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,7 @@ object CollectionStrawMan1 {
3636
}
3737

3838
/** Base trait for generic collections */
39-
trait Iterable[+IA] extends HasIterator[IA] with FromIterator[Iterable] {
40-
def buildIterator: Iterator[IA] = iterator
41-
}
39+
trait Iterable[+IA] extends HasIterator[IA] with FromIterator[Iterable]
4240

4341
/** Base trait for sequence collections */
4442
trait Seq[+AA] extends Iterable[AA] with FromIterator[Seq] {
@@ -50,67 +48,67 @@ object CollectionStrawMan1 {
5048

5149
/** Operations returning types unrelated to current collection */
5250
trait Ops[A] extends Any {
53-
def toIterator: Iterator[A]
54-
def foreach(f: A => Unit): Unit = toIterator.foreach(f)
55-
def foldLeft[B](z: B)(op: (B, A) => B): B = toIterator.foldLeft(z)(op)
56-
def foldRight[B](z: B)(op: (A, B) => B): B = toIterator.foldRight(z)(op)
57-
def indexWhere(p: A => Boolean): Int = toIterator.indexWhere(p)
58-
def head: A = toIterator.next
59-
def view: View[A] = new View(toIterator)
60-
def collect[C[X] <: Iterable[X]](fi: FromIterator[C]): C[A] = fi.fromIterator(toIterator)
51+
def iterator: Iterator[A]
52+
def foreach(f: A => Unit): Unit = iterator.foreach(f)
53+
def foldLeft[B](z: B)(op: (B, A) => B): B = iterator.foldLeft(z)(op)
54+
def foldRight[B](z: B)(op: (A, B) => B): B = iterator.foldRight(z)(op)
55+
def indexWhere(p: A => Boolean): Int = iterator.indexWhere(p)
56+
def head: A = iterator.next
57+
def view: View[A] = new View(iterator)
58+
def collect[C[X] <: Iterable[X]](fi: FromIterator[C]): C[A] = fi.fromIterator(iterator)
6159
}
6260

6361
/** Transforms returning same collection type */
6462
trait MonoTransforms[A, Repr] extends Any {
65-
def toIterator: Iterator[A]
66-
def fromIterator(it: => Iterator[A]): Repr
63+
protected def iter: Iterator[A]
64+
protected def fromIter(it: => Iterator[A]): Repr
6765
def partition(p: A => Boolean): (Repr, Repr) = {
68-
val (xs, ys) = toIterator.partition(p)
69-
(fromIterator(xs), fromIterator(ys))
66+
val (xs, ys) = iter.partition(p)
67+
(fromIter(xs), fromIter(ys))
7068
}
71-
def drop(n: Int): Repr = fromIterator(toIterator.drop(n))
69+
def drop(n: Int): Repr = fromIter(iter.drop(n))
7270
}
7371

7472
/** Transforms returning same collection type constructor */
7573
trait PolyTransforms[A, C[X]] extends Any {
76-
def toIterator: Iterator[A]
77-
def fromIterator[B](it: => Iterator[B]): C[B]
78-
def map[B](f: A => B): C[B] = fromIterator(toIterator.map(f))
79-
def flatMap[B](f: A => CanIterate[B]): C[B] = fromIterator(toIterator.flatMap(f(_)))
80-
def ++[B >: A](xs: CanIterate[B]): C[B] = fromIterator(toIterator ++ xs)
81-
def zip[B](xs: CanIterate[B]): C[(A, B)] = fromIterator(toIterator.zip(xs.iterator))
74+
protected def iter: Iterator[A]
75+
protected def fromIter[B](it: => Iterator[B]): C[B]
76+
def map[B](f: A => B): C[B] = fromIter(iter.map(f))
77+
def flatMap[B](f: A => CanIterate[B]): C[B] = fromIter(iter.flatMap(f(_)))
78+
def ++[B >: A](xs: CanIterate[B]): C[B] = fromIter(iter ++ xs)
79+
def zip[B](xs: CanIterate[B]): C[(A, B)] = fromIter(iter.zip(xs.iterator))
8280
}
8381

8482
/** Transforms that only apply to Seq */
8583
trait MonoTransformsOfSeqs[A, Repr] extends Any with MonoTransforms[A, Repr] {
86-
def reverse: Repr = fromIterator(toIterator.reverse)
84+
def reverse: Repr = fromIter(iter.reverse)
8785
}
8886

8987
/** Implementation of Ops for all generic collections */
9088
implicit class IterableOps[A](val c: Iterable[A])
9189
extends AnyVal with Ops[A] {
92-
def toIterator = c.iterator
90+
def iterator = c.iterator
9391
}
9492

9593
/** Implementation of MonoTransforms for all generic collections */
9694
implicit class IterableMonoTransforms[A, C[X] <: Iterable[X]](val c: Iterable[A] with FromIterator[C])
9795
extends AnyVal with MonoTransforms[A, C[A]] {
98-
def toIterator = c.buildIterator
99-
def fromIterator(it: => Iterator[A]): C[A] = c.fromIterator(it)
96+
protected def iter = c.iterator
97+
protected def fromIter(it: => Iterator[A]): C[A] = c.fromIterator(it)
10098
}
10199

102100
/** Implementation of PolyTransforms for all generic collections */
103101
implicit class IterablePolyTransforms[A, C[X] <: Iterable[X]](val c: Iterable[A] with FromIterator[C])
104102
extends AnyVal with PolyTransforms[A, C] {
105-
def toIterator = c.buildIterator
106-
def fromIterator[B](it: => Iterator[B]) = c.fromIterator(it)
103+
protected def iter = c.iterator
104+
protected def fromIter[B](it: => Iterator[B]) = c.fromIterator(it)
107105
}
108106

109107
/** Implementation of MonoTransformsForSeqs for all generic collections */
110108
implicit class SeqMonoTransforms[A, C[X] <: Seq[X]](val c: Seq[A] with FromIterator[C])
111109
extends AnyVal with MonoTransformsOfSeqs[A, C[A]] {
112-
def toIterator = c.buildIterator
113-
def fromIterator(it: => Iterator[A]) = c.fromIterator(it)
110+
protected def iter = c.iterator
111+
protected def fromIter(it: => Iterator[A]) = c.fromIterator(it)
114112
}
115113

116114
/* --------- Concrete collection types ------------------------------- */
@@ -156,41 +154,80 @@ object CollectionStrawMan1 {
156154
def tail = ???
157155
}
158156

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))
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+
}
168+
def fromIterator[B](it: Iterator[B]): ArrayBuffer[B] =
169+
ArrayBuffer.fromIterator(it)
170+
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
175+
}
176+
elems(len) = elem.asInstanceOf[AnyRef]
177+
len += 1
178+
this
179+
}
180+
override def toString = elems.take(len).deep.toString
181+
}
182+
183+
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)
187+
for (i <- 0 until elems.length) elems(i) = it.next.asInstanceOf[AnyRef]
188+
new ArrayBuffer(elems)
189+
}
190+
else {
191+
val buf = new ArrayBuffer[B]
192+
while (it.hasNext) buf += it.next
193+
buf
194+
}
195+
}
196+
159197
/** Concrete collection type: View */
160198
class View[+A](it: => Iterator[A]) extends HasIterator[A] {
161199
def iterator = it
162200
}
163201

164202
implicit class ViewOps[A](val v: View[A]) extends AnyVal with Ops[A] {
165-
def toIterator = v.iterator
166-
def cache = collect(List).view
203+
def iterator = v.iterator
204+
def cache = collect(ArrayBuffer).view
167205
}
168206

169207
implicit class ViewMonoTransforms[A](val v: View[A])
170208
extends AnyVal with MonoTransforms[A, View[A]] {
171-
def toIterator = v.iterator
172-
def fromIterator(it: => Iterator[A]): View[A] = new View(it)
209+
protected def iter = v.iterator
210+
protected def fromIter(it: => Iterator[A]): View[A] = new View(it)
173211
}
174212

175213
implicit class ViewPolyTransforms[A](val v: View[A])
176214
extends AnyVal with PolyTransforms[A, View] {
177-
def toIterator = v.iterator
178-
def fromIterator[B](it: => Iterator[B]) = new View(it)
215+
protected def iter = v.iterator
216+
protected def fromIter[B](it: => Iterator[B]) = new View(it)
179217
}
180218

181219
/** Concrete collection type: String */
182220
implicit class StringOps(val s: String) extends AnyVal with Ops[Char] {
183221
def iterator: Iterator[Char] = new RandomAccessIterator[Char] {
184-
def length = s.length
222+
override val knownLength = s.length
185223
def apply(n: Int) = s.charAt(n)
186224
}
187-
def toIterator = iterator
188225
}
189226

190227
implicit class StringMonoTransforms(val s: String)
191228
extends AnyVal with MonoTransformsOfSeqs[Char, String] {
192-
def toIterator = s.iterator
193-
def fromIterator(it: => Iterator[Char]) = {
229+
protected def iter = StringOps(s).iterator
230+
protected def fromIter(it: => Iterator[Char]) = {
194231
val sb = new StringBuilder
195232
for (ch <- it) sb.append(ch)
196233
sb.toString
@@ -199,8 +236,8 @@ object CollectionStrawMan1 {
199236

200237
implicit class StringPolyTransforms(val s: String)
201238
extends AnyVal with PolyTransforms[Char, Seq] {
202-
def toIterator = s.iterator
203-
def fromIterator[B](it: => Iterator[B]) = List.fromIterator(it)
239+
protected def iter = StringOps(s).iterator
240+
protected def fromIter[B](it: => Iterator[B]) = List.fromIterator(it)
204241
def map(f: Char => Char): String = {
205242
val sb = new StringBuilder
206243
for (ch <- s) sb.append(f(ch))
@@ -240,91 +277,107 @@ object CollectionStrawMan1 {
240277
}
241278
-1
242279
}
243-
def map[B](f: A => B): Iterator[B] = new Iterator[B] {
244-
def hasNext = self.hasNext
245-
def next = f(self.next)
246-
}
247-
def flatMap[B](f: A => CanIterate[B]): Iterator[B] = new Iterator[B] {
248-
private var myCurrent: Iterator[B] = Iterator.empty
249-
private def current = {
250-
while (!myCurrent.hasNext && self.hasNext) myCurrent = f(self.next).iterator
251-
myCurrent
252-
}
253-
def hasNext = current.hasNext
254-
def next = current.next
255-
}
256-
def ++[B >: A](xs: CanIterate[B]): Iterator[B] = new Iterator[B] {
257-
private var myCurrent: Iterator[B] = self
258-
private def current = {
259-
if (!myCurrent.hasNext && myCurrent.eq(self)) myCurrent = xs.iterator
260-
myCurrent
261-
}
262-
def hasNext = current.hasNext
263-
def next = current.next
264-
}
280+
def map[B](f: A => B): Iterator[B] = Iterator.Map(this, f)
281+
def flatMap[B](f: A => CanIterate[B]): Iterator[B] = Iterator.FlatMap(this, f)
282+
def ++[B >: A](xs: CanIterate[B]): Iterator[B] = Iterator.Concat(this, xs.iterator)
265283
def partition(p: A => Boolean): (Iterator[A], Iterator[A]) = {
266284
val lookaheadTrue, lookaheadFalse = new ListBuffer[A]
267-
class PartIterator[+A](buf: ListBuffer[A]) extends Iterator[A] {
268-
final def hasNext: Boolean =
269-
buf.nonEmpty ||
270-
self.hasNext && {
271-
val elem = self.next
272-
(if (p(elem)) lookaheadTrue else lookaheadFalse) += elem
273-
hasNext
274-
}
275-
final def next =
276-
if (hasNext) {
277-
val r = buf.head
278-
buf.trimStart(1)
279-
r
280-
}
281-
else Iterator.nextOnEmpty
282-
}
283-
(new PartIterator(lookaheadTrue), new PartIterator(lookaheadFalse))
284-
}
285-
def drop(n: Int): Iterator[A] = {
286-
if (n <= 0) this
287-
else {
288-
next
289-
drop(n - 1)
290-
}
291-
}
292-
def zip[B](that: CanIterate[B]): Iterator[(A, B)] = new Iterator[(A, B)] {
293-
val ti = that.iterator
294-
def hasNext = self.hasNext && ti.hasNext
295-
def next = (self.next, ti.next)
285+
(Iterator.Partition(this, p, lookaheadTrue, lookaheadFalse),
286+
Iterator.Partition[A](this, !p(_), lookaheadFalse, lookaheadTrue))
296287
}
288+
def drop(n: Int): Iterator[A] = Iterator.Drop(this, n)
289+
def zip[B](that: CanIterate[B]): Iterator[(A, B)] = Iterator.Zip(this, that.iterator)
297290
def reverse: Iterator[A] = {
298291
var elems: List[A] = Nil
299292
while (hasNext) elems = Cons(next, elems)
300293
elems.iterator
301294
}
295+
def underlying: Iterator[_] = this
296+
def knownLength = -1
302297
}
303298

304299
object Iterator {
305300
val empty: Iterator[Nothing] = new Iterator[Nothing] {
306301
def hasNext = false
307302
def next = ???
303+
override val knownLength = 0
308304
}
309305
def apply[A](xs: A*): Iterator[A] = new RandomAccessIterator[A] {
310-
def length = xs.length
306+
override val knownLength = xs.length
311307
def apply(n: Int) = xs(n)
312308
}
313309
def nextOnEmpty = throw new NoSuchElementException("next on empty iterator")
310+
311+
case class Map[A, B](override val underlying: Iterator[A], f: A => B) extends Iterator[B] {
312+
def hasNext = underlying.hasNext
313+
def next = f(underlying.next)
314+
override val knownLength = underlying.knownLength
315+
}
316+
case class FlatMap[A, B](override val underlying: Iterator[A], f: A => CanIterate[B]) extends Iterator[B] {
317+
private var myCurrent: Iterator[B] = Iterator.empty
318+
private def current = {
319+
while (!myCurrent.hasNext && underlying.hasNext)
320+
myCurrent = f(underlying.next).iterator
321+
myCurrent
322+
}
323+
def hasNext = current.hasNext
324+
def next = current.next
325+
}
326+
case class Concat[A](override val underlying: Iterator[A], other: Iterator[A]) extends Iterator[A] {
327+
private var myCurrent = underlying
328+
private def current = {
329+
if (!myCurrent.hasNext && myCurrent.eq(underlying)) myCurrent = other
330+
myCurrent
331+
}
332+
def hasNext = current.hasNext
333+
def next = current.next
334+
override val knownLength =
335+
if (underlying.knownLength > 0 && other.knownLength > 0)
336+
underlying.knownLength + other.knownLength
337+
else -1
338+
}
339+
case class Partition[A](override val underlying: Iterator[A], p: A => Boolean, lookahead: ListBuffer[A], dual: ListBuffer[A]) extends Iterator[A] {
340+
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+
}
347+
final def next =
348+
if (hasNext) {
349+
val r = lookahead.head
350+
lookahead.trimStart(1)
351+
r
352+
} else Iterator.nextOnEmpty
353+
}
354+
case class Drop[A](override val underlying: Iterator[A], n: Int) extends Iterator[A] {
355+
var toSkip = n
356+
def hasNext: Boolean = underlying.hasNext && (
357+
toSkip == 0 || { underlying.next; toSkip -= 1; hasNext })
358+
def next = if (hasNext) underlying.next else nextOnEmpty
359+
override val knownLength = (underlying.knownLength - n) max -1
360+
}
361+
case class Zip[A, B](override val underlying: Iterator[A], other: Iterator[B]) extends Iterator[(A, B)] {
362+
def hasNext = underlying.hasNext && other.hasNext
363+
def next = (underlying.next, other.next)
364+
override val knownLength = underlying.knownLength min other.knownLength
365+
}
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)
369+
}
314370
}
315371

316372
trait RandomAccessIterator[+A] extends Iterator[A] { self =>
317373
def apply(n: Int): A
318-
def length: Int
319-
protected val len = length
374+
def knownLength: Int
375+
def length: Int = knownLength
320376
private var cur = 0
321-
def hasNext = cur < len
377+
def hasNext = cur < knownLength
322378
def next: A = { val r = this(cur); cur += 1; r }
323379
override def drop(n: Int): Iterator[A] = { cur += (n max 0); this }
324-
override def reverse = new RandomAccessIterator[A] {
325-
def length = self.length
326-
def apply(n: Int) = apply(len - 1 - n)
327-
}
380+
override def reverse: Iterator[A] = new Iterator.Reverse(this)
328381
}
329382
}
330383

tests/run/CollectionTests.check

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,23 @@ 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)
31+
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)
35+
-------
36+
123
37+
123
38+
1
39+
1
40+
Cons(1,Cons(2,Cons(3,Nil)))
2441
Cons(2,Nil)
2542
Cons(1,Cons(3,Nil))
2643
Cons(3,Nil)

0 commit comments

Comments
 (0)