Correctly adding buffer this time. Adjusting buildables to type check and not recreate in the case that they're already of the right type.
authordavid@mel
Sat Apr 19 21:58:11 2008 +0100 (8 months ago)
changeset 5678d2f9ce2ff
parent 495de4825215f
child 6a5ee25f40be2
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;
+ }
+ }
+}