Skip to content

Commit 6f8741a

Browse files
committed
Add collection strawman and its tests
This compiles only after the changes in this branch.
1 parent 6497d02 commit 6f8741a

File tree

3 files changed

+500
-0
lines changed

3 files changed

+500
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
package strawman.collections
2+
3+
import Predef.{augmentString => _, wrapString => _, _}
4+
import scala.reflect.ClassTag
5+
import collection.mutable.ListBuffer
6+
7+
/** A strawman architecture for new collections. It contains some
8+
* example collection classes and methods with the intent to expose
9+
* some key issues. It would be good to compare this to other
10+
* implementations of the same functionality, to get an idea of the
11+
* strengths and weaknesses of different collection architectures.
12+
*
13+
* For a test file, see tests/run/CollectionTests.scala.
14+
*/
15+
object CollectionStrawMan1 {
16+
17+
/* ------------ Base Traits -------------------------------- */
18+
19+
/** Replaces TraversableOnce */
20+
trait CanIterate[+A] {
21+
def iterator: Iterator[A]
22+
}
23+
24+
/** Iterator guaranteed to be usable multiple times */
25+
trait HasIterator[+A] extends CanIterate[A]
26+
27+
/** Base trait for instances that can construct a collection from an iterator */
28+
trait FromIterator[+C[X] <: Iterable[X]] {
29+
def fromIterator[B](it: Iterator[B]): C[B]
30+
}
31+
32+
/** Base trait for companion objects of collections */
33+
trait IterableFactory[+C[X] <: Iterable[X]] extends FromIterator[C] {
34+
def empty[X]: C[X] = fromIterator(Iterator.empty)
35+
def apply[A](xs: A*): C[A] = fromIterator(Iterator(xs: _*))
36+
}
37+
38+
/** Base trait for generic collections */
39+
trait Iterable[+IA] extends HasIterator[IA] with FromIterator[Iterable] {
40+
def buildIterator: Iterator[IA] = iterator
41+
}
42+
43+
/** Base trait for sequence collections */
44+
trait Seq[+AA] extends Iterable[AA] with FromIterator[Seq] {
45+
def apply(i: Int): AA
46+
def length: Int
47+
}
48+
49+
/* ------------ Operations ----------------------------------- */
50+
51+
/** Operations returning types unrelated to current collection */
52+
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)
61+
}
62+
63+
/** Transforms returning same collection type */
64+
trait MonoTransforms[A, Repr] extends Any {
65+
def toIterator: Iterator[A]
66+
def fromIterator(it: => Iterator[A]): Repr
67+
def partition(p: A => Boolean): (Repr, Repr) = {
68+
val (xs, ys) = toIterator.partition(p)
69+
(fromIterator(xs), fromIterator(ys))
70+
}
71+
def drop(n: Int): Repr = fromIterator(toIterator.drop(n))
72+
}
73+
74+
/** Transforms returning same collection type constructor */
75+
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))
82+
}
83+
84+
/** Transforms that only apply to Seq */
85+
trait MonoTransformsOfSeqs[A, Repr] extends Any with MonoTransforms[A, Repr] {
86+
def reverse: Repr = fromIterator(toIterator.reverse)
87+
}
88+
89+
/** Implementation of Ops for all generic collections */
90+
implicit class IterableOps[A](val c: Iterable[A])
91+
extends AnyVal with Ops[A] {
92+
def toIterator = c.iterator
93+
}
94+
95+
/** Implementation of MonoTransforms for all generic collections */
96+
implicit class IterableMonoTransforms[A, C[X] <: Iterable[X]](val c: Iterable[A] with FromIterator[C])
97+
extends AnyVal with MonoTransforms[A, C[A]] {
98+
def toIterator = c.buildIterator
99+
def fromIterator(it: => Iterator[A]): C[A] = c.fromIterator(it)
100+
}
101+
102+
/** Implementation of PolyTransforms for all generic collections */
103+
implicit class IterablePolyTransforms[A, C[X] <: Iterable[X]](val c: Iterable[A] with FromIterator[C])
104+
extends AnyVal with PolyTransforms[A, C] {
105+
def toIterator = c.buildIterator
106+
def fromIterator[B](it: => Iterator[B]) = c.fromIterator(it)
107+
}
108+
109+
/** Implementation of MonoTransformsForSeqs for all generic collections */
110+
implicit class SeqMonoTransforms[A, C[X] <: Seq[X]](val c: Seq[A] with FromIterator[C])
111+
extends AnyVal with MonoTransformsOfSeqs[A, C[A]] {
112+
def toIterator = c.buildIterator
113+
def fromIterator(it: => Iterator[A]) = c.fromIterator(it)
114+
}
115+
116+
/* --------- Concrete collection types ------------------------------- */
117+
118+
/** Concrete collection type: List */
119+
sealed trait List[+A] extends Seq[A] with FromIterator[List] {
120+
def isEmpty: Boolean
121+
def head: A
122+
def tail: List[A]
123+
def iterator = new ListIterator[A](this)
124+
def fromIterator[B](it: Iterator[B]): List[B] = List.fromIterator(it)
125+
def apply(i: Int): A = {
126+
require(!isEmpty)
127+
if (i == 0) head else tail.apply(i - 1)
128+
}
129+
def length: Int =
130+
if (isEmpty) 0 else 1 + tail.length
131+
}
132+
133+
case class Cons[+A](x: A, xs: List[A]) extends List[A] {
134+
def isEmpty = false
135+
def head = x
136+
def tail = xs
137+
}
138+
139+
case object List extends IterableFactory[List] {
140+
def fromIterator[B](it: Iterator[B]): List[B] = it match {
141+
case it: ListIterator[B] => it.toList
142+
case _ => if (it.hasNext) Cons(it.next, fromIterator(it)) else Nil
143+
}
144+
}
145+
146+
class ListIterator[+A](xs: List[A]) extends Iterator[A] {
147+
private[this] var current = xs
148+
def hasNext = !current.isEmpty
149+
def next = { val r = current.head; current = current.tail; r }
150+
def toList = current
151+
}
152+
153+
case object Nil extends List[Nothing] {
154+
def isEmpty = true
155+
def head = ???
156+
def tail = ???
157+
}
158+
159+
/** Concrete collection type: View */
160+
class View[+A](it: => Iterator[A]) extends HasIterator[A] {
161+
def iterator = it
162+
}
163+
164+
implicit class ViewOps[A](val v: View[A]) extends AnyVal with Ops[A] {
165+
def toIterator = v.iterator
166+
def cache = collect(List).view
167+
}
168+
169+
implicit class ViewMonoTransforms[A](val v: View[A])
170+
extends AnyVal with MonoTransforms[A, View[A]] {
171+
def toIterator = v.iterator
172+
def fromIterator(it: => Iterator[A]): View[A] = new View(it)
173+
}
174+
175+
implicit class ViewPolyTransforms[A](val v: View[A])
176+
extends AnyVal with PolyTransforms[A, View] {
177+
def toIterator = v.iterator
178+
def fromIterator[B](it: => Iterator[B]) = new View(it)
179+
}
180+
181+
/** Concrete collection type: String */
182+
implicit class StringOps(val s: String) extends AnyVal with Ops[Char] {
183+
def iterator: Iterator[Char] = new RandomAccessIterator[Char] {
184+
def length = s.length
185+
def apply(n: Int) = s.charAt(n)
186+
}
187+
def toIterator = iterator
188+
}
189+
190+
implicit class StringMonoTransforms(val s: String)
191+
extends AnyVal with MonoTransformsOfSeqs[Char, String] {
192+
def toIterator = s.iterator
193+
def fromIterator(it: => Iterator[Char]) = {
194+
val sb = new StringBuilder
195+
for (ch <- it) sb.append(ch)
196+
sb.toString
197+
}
198+
}
199+
200+
implicit class StringPolyTransforms(val s: String)
201+
extends AnyVal with PolyTransforms[Char, Seq] {
202+
def toIterator = s.iterator
203+
def fromIterator[B](it: => Iterator[B]) = List.fromIterator(it)
204+
def map(f: Char => Char): String = {
205+
val sb = new StringBuilder
206+
for (ch <- s) sb.append(f(ch))
207+
sb.toString
208+
}
209+
def flatMap(f: Char => String) = {
210+
val sb = new StringBuilder
211+
for (ch <- s) sb.append(f(ch))
212+
sb.toString
213+
}
214+
def ++(xs: CanIterate[Char]): String = {
215+
val sb = new StringBuilder(s)
216+
for (ch <- xs.iterator) sb.append(ch)
217+
sb.toString
218+
}
219+
def ++(xs: String): String = s + xs
220+
}
221+
222+
/* ---------- Iterators --------------------------------------------------- */
223+
224+
/** A core Iterator class */
225+
trait Iterator[+A] extends CanIterate[A] { self =>
226+
def hasNext: Boolean
227+
def next: A
228+
def iterator = this
229+
def foldLeft[B](z: B)(op: (B, A) => B): B =
230+
if (hasNext) foldLeft(op(z, next))(op) else z
231+
def foldRight[B](z: B)(op: (A, B) => B): B =
232+
if (hasNext) op(next, foldRight(z)(op)) else z
233+
def foreach(f: A => Unit): Unit =
234+
while (hasNext) f(next)
235+
def indexWhere(p: A => Boolean): Int = {
236+
var i = 0
237+
while (hasNext) {
238+
if (p(next)) return i
239+
i += 1
240+
}
241+
-1
242+
}
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+
}
265+
def partition(p: A => Boolean): (Iterator[A], Iterator[A]) = {
266+
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)
296+
}
297+
def reverse: Iterator[A] = {
298+
var elems: List[A] = Nil
299+
while (hasNext) elems = Cons(next, elems)
300+
elems.iterator
301+
}
302+
}
303+
304+
object Iterator {
305+
val empty: Iterator[Nothing] = new Iterator[Nothing] {
306+
def hasNext = false
307+
def next = ???
308+
}
309+
def apply[A](xs: A*): Iterator[A] = new RandomAccessIterator[A] {
310+
def length = xs.length
311+
def apply(n: Int) = xs(n)
312+
}
313+
def nextOnEmpty = throw new NoSuchElementException("next on empty iterator")
314+
}
315+
316+
trait RandomAccessIterator[+A] extends Iterator[A] { self =>
317+
def apply(n: Int): A
318+
def length: Int
319+
protected val len = length
320+
private var cur = 0
321+
def hasNext = cur < len
322+
def next: A = { val r = this(cur); cur += 1; r }
323+
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+
}
328+
}
329+
}
330+

tests/run/CollectionTests.check

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Error: Could not find or load main class strawman.collections.Test

0 commit comments

Comments
 (0)