Correctly adding buffer this time. Adjusting buildables to type check and not recreate in the case that they're already of the right type.
--- a/src/sequence/list.scala Sat Apr 19 21:51:39 2008 +0100
+++ b/src/sequence/list.scala Sat Apr 19 21:58:11 2008 +0100
@@ -9,10 +9,13 @@ object List extends SequenceType{
type I[+T] = List[T];
def buildable[T] : Buildable[List, T] = new Buildable[List, T]{
- def build(contents : Traversable[T]) = {
- var rev : List[T] = Nil;
- contents.foreach(x => rev = x +: rev);
- rev.reverse;
+ def build(contents : Traversable[T]) = contents match {
+ case (contents : List[T]) => contents;
+ case _ => {
+ var rev : List[T] = Nil;
+ contents.foreach(x => rev = x +: rev);
+ rev.reverse;
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sequence/buffer.scala Sat Apr 19 21:58:11 2008 +0100
@@ -0,0 +1,77 @@
+package alt.collections.sequence;
+
+import buildable._;
+import Building._;
+import traversable._;
+
+object Buffer extends SequenceType{
+ type I[+T] = Buffer[T];
+
+ private def oob(msg : String) = throw new IndexOutOfBoundsException(msg);
+
+ val empty = new Buffer[Nothing](null, 0, 0);
+
+ def buildable[T] = new Buildable[Buffer, T] {
+ def build(c : Traversable[T]) = c match{
+ case (x : Buffer[T]) => x;
+ case _ => new Buffer[T](c.map(_.asInstanceOf[AnyRef]).as[Array, AnyRef]);
+ }
+ }
+
+ class Buffer[+T] private[sequence] (var contents : Array[AnyRef], // Monomorphic for performance reasons. :(
+ val from : Int,
+ val to : Int) extends Sequence[T]{
+ private[sequence] def this(contents : Array[AnyRef]) = this(contents, 0, contents.length);
+
+ if (from > to) oob("from > to");
+ def length = to - from;
+
+ def trim : Buffer[T] = { contents = contents.slice(from, to).force; this }
+
+ def apply(i : Int) = contents(adjust(i)).asInstanceOf[T];
+
+ def traverse(f : T => Unit) = Traversable.range(from, to).map(contents).foreach(x => f(x.asInstanceOf[T]));
+
+ def :+[S >: T](s : S) = {
+ if (to < contents.length && (s.asInstanceOf[AnyRef] eq contents(to))) new Buffer[T](contents, from, to + 1);
+ else {
+ val newcontents = new Array[AnyRef](length + 1);
+ contents.slice(from, to).copyToArray(newcontents, 0);
+ newcontents(length) = s.asInstanceOf[AnyRef];
+ new Buffer[S](newcontents);
+ }
+ }
+
+ def +:[S >: T](s : S) = {
+ if (from > 0 && (s.asInstanceOf[AnyRef] eq contents(from - 1))) new Buffer[T](contents, from - 1, to);
+ else {
+ val newcontents = new Array[AnyRef](length + 1);
+ contents.slice(from, to).copyToArray(newcontents, 1);
+ newcontents(0) = s.asInstanceOf[AnyRef];
+ new Buffer[S](newcontents);
+ }
+ }
+
+ def ++[S >: T](that : Buffer[S]) = {
+ if ((contents == that.contents) && (to == that.from)) new Buffer[S](contents, from, that.to);
+ else {
+ val newcontents = new Array[AnyRef](that.to - from);
+ contents.slice(from, to).copyToArray(newcontents, 0);
+ that.contents.slice(that.from, that.to).copyToArray(newcontents, length);
+ new Buffer[S](newcontents);
+ }
+ }
+
+ override def slice(f : Int, t : Int) = {
+ if (f > t || f + from > to) empty;
+ else new Buffer[T](contents, f + from, Math.min(to, f + t));
+ }
+
+ private def adjust(i : Int) = {
+ if (i < 0) oob(i + " < 0");
+ val index = i + from;
+ if (index >= to) oob(i + " > " + length );
+ index;
+ }
+ }
+}