Changed the structure of Buildable as per Jamie Webb's excellent suggestion.
authordavid@mel
Sat Apr 19 21:51:39 2008 +0100 (8 months ago)
changeset 495de4825215f
parent 3e63ca8b0db7e
child 5678d2f9ce2ff
Changed the structure of Buildable as per Jamie Webb's excellent suggestion.

Added a "Buffer" type - basically an immutable slice of an array.
--- a/src/buildable.scala Sat Apr 19 16:58:18 2008 +0100
+++ b/src/buildable.scala Sat Apr 19 21:51:39 2008 +0100
@@ -4,16 +4,10 @@ import mutable._;
import mutable._;
import sequence._;
import List.List;
-
-trait Builder[I[_], T]{
- def += (t : T) : Unit;
- def ++= (ts : T*) = for (t <- ts) { this += t }
- def build : I[T];
-}
+import traversable._;
trait Buildable[I[_], T]{
- def builder () : Builder[I, T]
- def builderOfCapacity(n : Int) : Builder[I, T ] = builder();
+ def build(contents : Traversable[T]) : I[T];
}
/**
@@ -23,31 +17,30 @@ object Building{
implicit def listIsBuildable[T] : Buildable[List, T] = List.buildable
implicit def scalaListIsBuildable[T] : Buildable[scala.List, T] = new Buildable[scala.List, T]{
- def builder () = new Builder[scala.List, T]{
- val buffer = new ListBuffer[T]();
- def += (t : T) = buffer += t;
- def build = buffer.toList;
- }
- }
-
- implicit def immutableSetIsBuildable[T] = new Buildable[immutable.Set, T]{
- def builder () = new Builder[immutable.Set, T]{
- val buffer = new ListBuffer[T]();
- def += (t : T) = buffer += t;
- def build = immutable.Set(buffer.toList :_*);
+ def build (contents : Traversable[T]) = {
+ val buffer = new ListBuffer[T];
+ contents.foreach(buffer += (_ : T));
+ buffer.toList;
}
}
implicit def arrayIsBuildable[T] = new Buildable[Array, T]{
- class ArrayBuilder(buffer : ArrayBuffer[T]) extends Builder[Array, T]{
- def += (t : T) = (buffer += t);
- def build = buffer.toArray;
- }
-
- def builder () = new ArrayBuilder(new ArrayBuffer[T])
- override def builderOfCapacity(n : Int) = new ArrayBuilder(new ArrayBuffer[T]{
- ensureSize(n);
- });
+ def build(contents : Traversable[T]) = contents.knownSize match {
+ case Some(i) => {
+ val result = new Array[T](i);
+ var j = 0;
+ contents.foreach(x => {
+ result(j) = x;
+ j = j + 1;
+ })
+ result;
+ }
+ case None => {
+ val buffer = new ArrayBuffer[T];
+ contents.foreach(x => buffer += x);
+ buffer.toArray;
+ }
+ }
}
}
--- a/src/sequence/list.scala Sat Apr 19 16:58:18 2008 +0100
+++ b/src/sequence/list.scala Sat Apr 19 21:51:39 2008 +0100
@@ -9,7 +9,11 @@ object List extends SequenceType{
type I[+T] = List[T];
def buildable[T] : Buildable[List, T] = new Buildable[List, T]{
- def builder() = new ListBuilder[T];
+ def build(contents : Traversable[T]) = {
+ var rev : List[T] = Nil;
+ contents.foreach(x => rev = x +: rev);
+ rev.reverse;
+ }
}
def empty = Nil
@@ -63,12 +67,6 @@ object List extends SequenceType{
def ++[S >: T](that : List[S]) : List[S] = reverse.reversePrepend(that);
}
- class ListBuilder[T] extends Builder[List, T]{
- var built : List[T] = Nil;
- def +=(t : T) = built = t +: built;
- def build : List[T] = built.reverse;
- }
-
case class Cons[+T](head : T, tail : List[T]) extends List[T]{
override def isEmpty = false;
val length = 1 + tail.length;
--- a/src/traversable.scala Sat Apr 19 16:58:18 2008 +0100
+++ b/src/traversable.scala Sat Apr 19 21:51:39 2008 +0100
@@ -22,6 +22,7 @@ trait Traversable[+T]{
new Traversable[S]{
def traverse(g : S => Unit) = outer.traverse(g.compose(f));
override def map[R](g : S => R) = outer.map(g.compose(f));
+ override def knownSize = outer.knownSize;
}
}
@@ -43,11 +44,7 @@ trait Traversable[+T]{
def exists(f : T => Boolean) : Boolean = !filter(f).isEmpty
def forall(f : T => Boolean) : Boolean = !exists(x => !f(x));
- def as[M[_], S >: T](implicit buildable : Buildable[M, S]) : M[S] = {
- val builder = buildable.builder;
- foreach(x => builder += x);
- builder.build;
- }
+ def as[M[_], S >: T](implicit buildable : Buildable[M, S]) : M[S] = buildable.build(this);
def intersperse[S >: T](t : S) = {
val outer = this;
@@ -64,7 +61,7 @@ trait Traversable[+T]{
}
def take(i : Int) : Traversable[T] = {
- val outer = this;
+ val outer = this;
new Traversable[T]{
def traverse(f : T => Unit) {
var j = i;
@@ -77,13 +74,16 @@ trait Traversable[+T]{
})
}
+ override def knownSize = outer.knownSize.map(j => Math.min(i, j));
override def take(j : Int) = outer.take(Math.min(i, j));
}
}
def drop(dropped : Int) : Traversable[T] = {
val outer = this;
- new Traversable[T]{
+
+ if (knownSize.map(x => x < dropped).getOrElse(false)) Traversable.empty
+ else new Traversable[T]{
def traverse(f : T => Unit) {
var i = 0;
outer.traverse(x => {
@@ -91,9 +91,13 @@ trait Traversable[+T]{
else i = i + 1;
});
}
+
+ override def knownSize = outer.knownSize.map(n => n - dropped);
}
}
+
+ def knownSize : Option[Int] = None;
def takeWhile(f : T => Boolean) : Traversable[T] = {
val outer = this;
@@ -101,8 +105,23 @@ trait Traversable[+T]{
def traverse(g : T => Unit) {
outer.traverse(x => if (!f(x)) break else g(x));
}
+ }
+ }
- override def takeWhile(g : T => Boolean) = outer.takeWhile(x => f(x) && g(x));
+ def dropWhile(f : T => Boolean) : Traversable[T] = {
+ val outer = this;
+ new Traversable[T]{
+ def traverse(g : T => Unit) {
+ var seen = false;
+ outer.traverse(x => if (seen || !f(x)) { seen = true; g(x) });
+ }
+ }
+ }
+
+ def concat[S >: T](that : Traversable[S]) : Traversable[S] = {
+ val outer = this;
+ new Traversable[S]{
+ def traverse(g : S => Unit) { outer.traverse(g); that.traverse(g); }
}
}
@@ -134,8 +153,13 @@ trait Traversable[+T]{
}
object Traversable{
- def fromIterable[T](it : Iterable[T]) = new Traversable[T]{
+ implicit def fromIterable[T](it : Iterable[T]) = new Traversable[T]{
def traverse(f : T => Unit) = it.foreach(f);
+
+ override def knownSize = it match {
+ case (it : Collection[_]) => Some(it.size);
+ case _ => None;
+ }
}
val empty = new Traversable[Nothing]{