summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-05-12 14:30:04 +0000
committerPaul Phillips <paulp@improving.org>2009-05-12 14:30:04 +0000
commite326df2c225eefcfd058e19963d3a7fdf366637d (patch)
treef057e66f66925670a1aea6761e33e174d95365b0 /src/library
parent93ce8b0c6cb98c3bb9cb1ab67e17c678ff86ab1a (diff)
downloadscala-e326df2c225eefcfd058e19963d3a7fdf366637d.tar.gz
scala-e326df2c225eefcfd058e19963d3a7fdf366637d.tar.bz2
scala-e326df2c225eefcfd058e19963d3a7fdf366637d.zip
This patch includes the following:
1) Default Ordering implementations for various built-in types, supplied by DrMacIver. Ticket #1303. 2) Implicits for scala.Numeric and scala.Ordering so classes implementing those can use punctuation and, more importantly, infix notation. Compare "minus(plus(x, y), z)" to "x + y - z". 3) A generic implementation of Range, but leaving the original Int-only Range untouched. A LongRange. 4) Numeric and Ordering implementations of BigInt, as required for the new BigIntRange. Ticket #931. 5) Numeric implementations for built-in types changed to the trait + implicit-object-extends-trait model so the implementation can be mixed into other objects - in particular one might easily want to combine Numeric[T] and Ordering[T] in one object. 6) Assorted tweaks to support all the above.
Diffstat (limited to 'src/library')
-rwxr-xr-xsrc/library/scala/Fractional.scala5
-rwxr-xr-xsrc/library/scala/Integral.scala6
-rwxr-xr-xsrc/library/scala/Numeric.scala48
-rw-r--r--src/library/scala/Ordering.scala245
-rw-r--r--src/library/scala/Range.scala137
5 files changed, 434 insertions, 7 deletions
diff --git a/src/library/scala/Fractional.scala b/src/library/scala/Fractional.scala
index 81366a80b9..c8905ce5fd 100755
--- a/src/library/scala/Fractional.scala
+++ b/src/library/scala/Fractional.scala
@@ -2,4 +2,9 @@ package scala
trait Fractional[T] extends Numeric[T] {
def div(x: T, y: T): T
+
+ class FractionalOps(lhs: T) extends Ops(lhs) {
+ def /(rhs: T) = div(lhs, rhs)
+ }
+ override implicit def mkNumericOps(lhs: T): FractionalOps = new FractionalOps(lhs)
}
diff --git a/src/library/scala/Integral.scala b/src/library/scala/Integral.scala
index bfd4bf9f48..425cccdb48 100755
--- a/src/library/scala/Integral.scala
+++ b/src/library/scala/Integral.scala
@@ -3,4 +3,10 @@ package scala
trait Integral[T] extends Numeric[T] {
def quot(x: T, y: T): T
def rem(x: T, y: T): T
+
+ class IntegralOps(lhs: T) extends Ops(lhs) {
+ def /(rhs: T) = quot(lhs, rhs)
+ def %(rhs: T) = rem(lhs, rhs)
+ }
+ override implicit def mkNumericOps(lhs: T): IntegralOps = new IntegralOps(lhs)
}
diff --git a/src/library/scala/Numeric.scala b/src/library/scala/Numeric.scala
index 4f7e4749cf..ba48db9c1d 100755
--- a/src/library/scala/Numeric.scala
+++ b/src/library/scala/Numeric.scala
@@ -1,7 +1,24 @@
package scala
object Numeric {
- implicit object IntIsIntegral extends Integral[Int] {
+ trait BigIntIsIntegral extends Integral[BigInt] {
+ def plus(x: BigInt, y: BigInt): BigInt = x + y
+ def minus(x: BigInt, y: BigInt): BigInt = x - y
+ def times(x: BigInt, y: BigInt): BigInt = x * y
+ def quot(x: BigInt, y: BigInt): BigInt = x / y
+ def rem(x: BigInt, y: BigInt): BigInt = x % y
+ def negate(x: BigInt): BigInt = -x
+ def abs(x: BigInt): BigInt = if (x < 0) -x else x
+ def signum(x: BigInt): BigInt = if (x < 0) -1 else if (x > 0) 1 else 0
+ def fromInt(x: Int): BigInt = BigInt(x)
+ def toInt(x: BigInt): Int = x.intValue
+ def toLong(x: BigInt): Long = x.longValue
+ def toFloat(x: BigInt): Float = x.longValue.toFloat
+ def toDouble(x: BigInt): Double = x.longValue.toDouble
+ }
+ implicit object BigIntIsIntegral extends BigIntIsIntegral
+
+ trait IntIsIntegral extends Integral[Int] {
def plus(x: Int, y: Int): Int = x + y
def minus(x: Int, y: Int): Int = x - y
def times(x: Int, y: Int): Int = x * y
@@ -16,7 +33,9 @@ object Numeric {
def toFloat(x: Int): Float = x
def toDouble(x: Int): Double = x
}
- implicit object LongIsIntegral extends Integral[Long] {
+ implicit object IntIsIntegral extends IntIsIntegral
+
+ trait LongIsIntegral extends Integral[Long] {
def plus(x: Long, y: Long): Long = x + y
def minus(x: Long, y: Long): Long = x - y
def times(x: Long, y: Long): Long = x * y
@@ -31,7 +50,9 @@ object Numeric {
def toFloat(x: Long): Float = x
def toDouble(x: Long): Double = x
}
- implicit object FloatIsFractional extends Fractional[Float] {
+ implicit object LongIsIntegral extends LongIsIntegral
+
+ trait FloatIsFractional extends Fractional[Float] {
def plus(x: Float, y: Float): Float = x + y
def minus(x: Float, y: Float): Float = x - y
def times(x: Float, y: Float): Float = x * y
@@ -45,7 +66,9 @@ object Numeric {
def toFloat(x: Float): Float = x
def toDouble(x: Float): Double = x
}
- implicit object DoubleIsFractional extends Fractional[Double] {
+ implicit object FloatIsFractional extends FloatIsFractional
+
+ trait DoubleIsFractional extends Fractional[Double] {
def plus(x: Double, y: Double): Double = x + y
def minus(x: Double, y: Double): Double = x - y
def times(x: Double, y: Double): Double = x * y
@@ -59,8 +82,9 @@ object Numeric {
def toFloat(x: Double): Float = x.toFloat
def toDouble(x: Double): Double = x
}
-}
+ implicit object DoubleIsFractional extends DoubleIsFractional
+}
trait Numeric[T] {
def plus(x: T, y: T): T
@@ -76,4 +100,18 @@ trait Numeric[T] {
def toDouble(x: T): Double
def zero = fromInt(0)
def one = fromInt(1)
+
+ class Ops(lhs: T) {
+ def +(rhs: T) = plus(lhs, rhs)
+ def -(rhs: T) = minus(lhs, rhs)
+ def *(rhs: T) = times(lhs, rhs)
+ def unary_-() = negate(lhs)
+ def abs(): T = Numeric.this.abs(lhs)
+ def signum(): T = Numeric.this.signum(lhs)
+ def toInt(): Int = Numeric.this.toInt(lhs)
+ def toLong(): Long = Numeric.this.toLong(lhs)
+ def toFloat(): Float = Numeric.this.toFloat(lhs)
+ def toDouble(): Double = Numeric.this.toDouble(lhs)
+ }
+ implicit def mkNumericOps(lhs: T): Ops = new Ops(lhs)
}
diff --git a/src/library/scala/Ordering.scala b/src/library/scala/Ordering.scala
index 9b18cb7e0c..663af258dd 100644
--- a/src/library/scala/Ordering.scala
+++ b/src/library/scala/Ordering.scala
@@ -71,4 +71,249 @@ trait Ordering[T] extends PartialOrdering[T] {
* <code>y</code> in the ordering.
*/
override def equiv(x: T, y: T): Boolean = compare(x, y) == 0
+
+ class Ops(lhs: T) {
+ def <(rhs: T) = lt(lhs, rhs)
+ def <=(rhs: T) = lteq(lhs, rhs)
+ def >(rhs: T) = gt(lhs, rhs)
+ def >=(rhs: T) = gteq(lhs, rhs)
+ def ===(rhs: T) = equiv(lhs, rhs)
+ def !==(rhs: T) = !equiv(lhs, rhs)
+ }
+ implicit def mkOrderingOps(lhs: T): Ops = new Ops(lhs)
+}
+
+object Ordering
+{
+ def apply[T](implicit ord : Ordering[T]) = ord
+
+ implicit val Unit : Ordering[Unit] = new Ordering[Unit] {
+ def compare(x : Unit, y : Unit) = 0;
+ }
+
+ implicit val Boolean : Ordering[Boolean] = new Ordering[Boolean] {
+ def compare(x : Boolean, y : Boolean) = (x, y) match {
+ case (false, true) => -1;
+ case (true, false) => 1;
+ case _ => 0;
+ }
+ }
+
+ implicit val Byte : Ordering[Byte] = new Ordering[Byte] {
+ def compare(x : Byte, y : Byte) = x.toInt - y.toInt;
+ }
+
+ implicit val Char : Ordering[Char] = new Ordering[Char] {
+ def compare(x : Char, y : Char) = x.toInt - y.toInt;
+ }
+
+ implicit val Short : Ordering[Short] = new Ordering[Short] {
+ def compare(x : Short, y : Short) = x.toInt - y.toInt;
+ }
+
+ implicit val Int : Ordering[Int] = new Ordering[Int] {
+ def compare(x : Int, y : Int) =
+ if(x < y) -1;
+ else if (x == y) 0;
+ else 1
+ }
+
+ implicit val Long : Ordering[Long] = new Ordering[Long] {
+ def compare(x : Long, y : Long) =
+ if(x < y) -1;
+ else if (x == y) 0;
+ else 1
+ }
+
+ implicit val Float : Ordering[Float] = new Ordering[Float] {
+ def compare(x : Float, y : Float) =
+ if(x < y) -1;
+ else if (x == y) 0;
+ else 1
+ }
+
+ implicit val Double : Ordering[Double] = new Ordering[Double] {
+ def compare(x : Double, y : Double) =
+ if(x < y) -1;
+ else if (x == y) 0;
+ else 1
+ }
+
+ implicit val BigInt : Ordering[BigInt] = new Ordering[BigInt] {
+ def compare(x : BigInt, y : BigInt) = x.compare(y);
+ }
+
+ implicit val String : Ordering[String] = new Ordering[String] {
+ def compare(x : String, y : String) = x.compareTo(y);
+ }
+
+ implicit def Option[T](implicit ord : Ordering[T]) : Ordering[Option[T]] =
+ new Ordering[Option[T]] {
+ def compare(x : Option[T], y : Option[T]) = (x, y) match {
+ case (None, None) => 0;
+ case (None, _) => -1;
+ case (_, None) => 1
+ case (Some(x), Some(y)) => ord.compare(x, y);
+ }
+ }
+
+ implicit def Iterable[T](implicit ord : Ordering[T]) : Ordering[Iterable[T]] =
+ new Ordering[Iterable[T]] {
+ def compare(x : Iterable[T], y : Iterable[T]) : Int = {
+ val xe = x.elements;
+ val ye = y.elements;
+
+ while (xe.hasNext && ye.hasNext){
+ val res = ord.compare(xe.next, ye.next);
+ if (res != 0) return res;
+ }
+
+ Boolean.compare(xe.hasNext, ye.hasNext);
+ }
+ }
+
+ implicit def Tuple2[T1, T2](implicit ord1 : Ordering[T1], ord2 : Ordering[T2]) : Ordering[(T1, T2)] =
+ new Ordering[(T1, T2)]{
+ def compare(x : Tuple2[T1, T2], y : Tuple2[T1, T2]) : Int = {
+ val compare1 = ord1.compare(x._1, y._1);
+ if (compare1 != 0) return compare1;
+ val compare2 = ord2.compare(x._2, y._2);
+ if (compare2 != 0) return compare2;
+ 0;
+ }
+ }
+
+ implicit def Tuple3[T1, T2, T3](implicit ord1 : Ordering[T1], ord2 : Ordering[T2], ord3 : Ordering[T3]) : Ordering[(T1, T2, T3)] =
+ new Ordering[(T1, T2, T3)]{
+ def compare(x : Tuple3[T1, T2, T3], y : Tuple3[T1, T2, T3]) : Int = {
+ val compare1 = ord1.compare(x._1, y._1);
+ if (compare1 != 0) return compare1;
+ val compare2 = ord2.compare(x._2, y._2);
+ if (compare2 != 0) return compare2;
+ val compare3 = ord3.compare(x._3, y._3);
+ if (compare3 != 0) return compare3;
+ 0;
+ }
+ }
+
+ implicit def Tuple4[T1, T2, T3, T4](implicit ord1 : Ordering[T1], ord2 : Ordering[T2], ord3 : Ordering[T3], ord4 : Ordering[T4]) : Ordering[(T1, T2, T3, T4)] =
+ new Ordering[(T1, T2, T3, T4)]{
+ def compare(x : Tuple4[T1, T2, T3, T4], y : Tuple4[T1, T2, T3, T4]) : Int = {
+ val compare1 = ord1.compare(x._1, y._1);
+ if (compare1 != 0) return compare1;
+ val compare2 = ord2.compare(x._2, y._2);
+ if (compare2 != 0) return compare2;
+ val compare3 = ord3.compare(x._3, y._3);
+ if (compare3 != 0) return compare3;
+ val compare4 = ord4.compare(x._4, y._4);
+ if (compare4 != 0) return compare4;
+ 0;
+ }
+ }
+
+ implicit def Tuple5[T1, T2, T3, T4, T5](implicit ord1 : Ordering[T1], ord2 : Ordering[T2], ord3 : Ordering[T3], ord4 : Ordering[T4], ord5 : Ordering[T5]) : Ordering[(T1, T2, T3, T4, T5)] =
+ new Ordering[(T1, T2, T3, T4, T5)]{
+ def compare(x : Tuple5[T1, T2, T3, T4, T5], y : Tuple5[T1, T2, T3, T4, T5]) : Int = {
+ val compare1 = ord1.compare(x._1, y._1);
+ if (compare1 != 0) return compare1;
+ val compare2 = ord2.compare(x._2, y._2);
+ if (compare2 != 0) return compare2;
+ val compare3 = ord3.compare(x._3, y._3);
+ if (compare3 != 0) return compare3;
+ val compare4 = ord4.compare(x._4, y._4);
+ if (compare4 != 0) return compare4;
+ val compare5 = ord5.compare(x._5, y._5);
+ if (compare5 != 0) return compare5;
+ 0;
+ }
+ }
+
+ implicit def Tuple6[T1, T2, T3, T4, T5, T6](implicit ord1 : Ordering[T1], ord2 : Ordering[T2], ord3 : Ordering[T3], ord4 : Ordering[T4], ord5 : Ordering[T5], ord6 : Ordering[T6]) : Ordering[(T1, T2, T3, T4, T5, T6)] =
+ new Ordering[(T1, T2, T3, T4, T5, T6)]{
+ def compare(x : Tuple6[T1, T2, T3, T4, T5, T6], y : Tuple6[T1, T2, T3, T4, T5, T6]) : Int = {
+ val compare1 = ord1.compare(x._1, y._1);
+ if (compare1 != 0) return compare1;
+ val compare2 = ord2.compare(x._2, y._2);
+ if (compare2 != 0) return compare2;
+ val compare3 = ord3.compare(x._3, y._3);
+ if (compare3 != 0) return compare3;
+ val compare4 = ord4.compare(x._4, y._4);
+ if (compare4 != 0) return compare4;
+ val compare5 = ord5.compare(x._5, y._5);
+ if (compare5 != 0) return compare5;
+ val compare6 = ord6.compare(x._6, y._6);
+ if (compare6 != 0) return compare6;
+ 0;
+ }
+ }
+
+ implicit def Tuple7[T1, T2, T3, T4, T5, T6, T7](implicit ord1 : Ordering[T1], ord2 : Ordering[T2], ord3 : Ordering[T3], ord4 : Ordering[T4], ord5 : Ordering[T5], ord6 : Ordering[T6], ord7 : Ordering[T7]) : Ordering[(T1, T2, T3, T4, T5, T6, T7)] =
+ new Ordering[(T1, T2, T3, T4, T5, T6, T7)]{
+ def compare(x : Tuple7[T1, T2, T3, T4, T5, T6, T7], y : Tuple7[T1, T2, T3, T4, T5, T6, T7]) : Int = {
+ val compare1 = ord1.compare(x._1, y._1);
+ if (compare1 != 0) return compare1;
+ val compare2 = ord2.compare(x._2, y._2);
+ if (compare2 != 0) return compare2;
+ val compare3 = ord3.compare(x._3, y._3);
+ if (compare3 != 0) return compare3;
+ val compare4 = ord4.compare(x._4, y._4);
+ if (compare4 != 0) return compare4;
+ val compare5 = ord5.compare(x._5, y._5);
+ if (compare5 != 0) return compare5;
+ val compare6 = ord6.compare(x._6, y._6);
+ if (compare6 != 0) return compare6;
+ val compare7 = ord7.compare(x._7, y._7);
+ if (compare7 != 0) return compare7;
+ 0;
+ }
+ }
+
+ implicit def Tuple8[T1, T2, T3, T4, T5, T6, T7, T8](implicit ord1 : Ordering[T1], ord2 : Ordering[T2], ord3 : Ordering[T3], ord4 : Ordering[T4], ord5 : Ordering[T5], ord6 : Ordering[T6], ord7 : Ordering[T7], ord8 : Ordering[T8]) : Ordering[(T1, T2, T3, T4, T5, T6, T7, T8)] =
+ new Ordering[(T1, T2, T3, T4, T5, T6, T7, T8)]{
+ def compare(x : Tuple8[T1, T2, T3, T4, T5, T6, T7, T8], y : Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) : Int = {
+ val compare1 = ord1.compare(x._1, y._1);
+ if (compare1 != 0) return compare1;
+ val compare2 = ord2.compare(x._2, y._2);
+ if (compare2 != 0) return compare2;
+ val compare3 = ord3.compare(x._3, y._3);
+ if (compare3 != 0) return compare3;
+ val compare4 = ord4.compare(x._4, y._4);
+ if (compare4 != 0) return compare4;
+ val compare5 = ord5.compare(x._5, y._5);
+ if (compare5 != 0) return compare5;
+ val compare6 = ord6.compare(x._6, y._6);
+ if (compare6 != 0) return compare6;
+ val compare7 = ord7.compare(x._7, y._7);
+ if (compare7 != 0) return compare7;
+ val compare8 = ord8.compare(x._8, y._8);
+ if (compare8 != 0) return compare8;
+ 0;
+ }
+ }
+
+ implicit def Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9](implicit ord1 : Ordering[T1], ord2 : Ordering[T2], ord3 : Ordering[T3], ord4 : Ordering[T4], ord5 : Ordering[T5], ord6 : Ordering[T6], ord7 : Ordering[T7], ord8 : Ordering[T8], ord9 : Ordering[T9]) : Ordering[(T1, T2, T3, T4, T5, T6, T7, T8, T9)] =
+ new Ordering[(T1, T2, T3, T4, T5, T6, T7, T8, T9)]{
+ def compare(x : Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9], y : Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) : Int = {
+ val compare1 = ord1.compare(x._1, y._1);
+ if (compare1 != 0) return compare1;
+ val compare2 = ord2.compare(x._2, y._2);
+ if (compare2 != 0) return compare2;
+ val compare3 = ord3.compare(x._3, y._3);
+ if (compare3 != 0) return compare3;
+ val compare4 = ord4.compare(x._4, y._4);
+ if (compare4 != 0) return compare4;
+ val compare5 = ord5.compare(x._5, y._5);
+ if (compare5 != 0) return compare5;
+ val compare6 = ord6.compare(x._6, y._6);
+ if (compare6 != 0) return compare6;
+ val compare7 = ord7.compare(x._7, y._7);
+ if (compare7 != 0) return compare7;
+ val compare8 = ord8.compare(x._8, y._8);
+ if (compare8 != 0) return compare8;
+ val compare9 = ord9.compare(x._9, y._9);
+ if (compare9 != 0) return compare9;
+ 0;
+ }
+ }
+
}
diff --git a/src/library/scala/Range.scala b/src/library/scala/Range.scala
index 016ea5fc03..8a6ba86bff 100644
--- a/src/library/scala/Range.scala
+++ b/src/library/scala/Range.scala
@@ -8,13 +8,143 @@
// $Id$
-
package scala
import collection.immutable.Vector
import collection.generic.VectorView
/** <p>
+ * <code>GenericRange</code> is a generified version of the
+ * <code>Range</code> class which works with arbitrary types.
+ * It must be supplied with Integral and Ordering implementations
+ * of the range type.
+ *
+ * Built-in incarnations include BigIntRange and LongRange.
+ * </p><pre>
+ * <b>val</b> r1 = new Range(0, 100, 1)
+ * <b>val</b> veryBig = Math.MAX_INT.toLong + 1
+ * <b>val</b> r2 = new LongRange(veryBig, veryBig + 100, 1)
+ * assert(r1 sameElements r2.map(_ - veryBig))
+ * </pre>
+ *
+ * @author Paul Phillips
+ * @version 2.8
+ */
+class GenericRange[T]
+ (val start: T, val end: T, val step: T)
+ (implicit num: Integral[T], ord: Ordering[T])
+extends VectorView[T, Vector[T]] with RangeToString[T] {
+ import num._
+ import ord._
+
+ // todo? - we could lift the length restriction by implementing a range as a sequence of
+ // subranges and limiting the subranges to MAX_INT. There's no other way around it because
+ // the generics we inherit assume integer-based indexing (as well they should.)
+ require(step !== zero)
+ require(genericLength <= fromInt(Math.MAX_INT), "Implementation restricts ranges to Math.MAX_INT elements.")
+
+ protected def underlying = Vector.empty[T]
+
+ /** Create a new range with the start and end values of this range and
+ * a new <code>step</code>.
+ */
+ def by(step: T): GenericRange[T] = new GenericRange(start, end, step)
+
+ override def foreach[U](f: T => U) {
+ var i = start
+ if (step > zero) {
+ while (i < end) {
+ f(i)
+ i = i + step
+ }
+ } else {
+ while (i > end) {
+ f(i)
+ i = i + step
+ }
+ }
+ }
+
+ lazy val genericLength: T = {
+ def plen(start: T, end: T, step: T) =
+ if (end <= start) zero
+ else (end - start - one) / step + one
+ // if (lteq(end, start)) zero
+ // else plus(quot((minus(minus(end, start), one)), step), one)
+
+ if (step > zero) plen(start, end, step)
+ else plen(end, start, -step)
+ }
+ lazy val length: Int = toInt(genericLength)
+
+ // Since apply(Int) already exists, we are not allowed apply(T) since
+ // they erase to the same thing.
+ def apply(idx: Int): T = applyAt(fromInt(idx))
+ def applyAt(idx: T): T = {
+ if (idx < zero || idx >= genericLength) throw new IndexOutOfBoundsException(idx.toString)
+ start + idx * step
+ }
+
+ override def contains(_x: Any): Boolean = {
+ // XXX - can we avoid this cast and still have a contains method?
+ val x =
+ try { _x.asInstanceOf[T] }
+ catch { case _: ClassCastException => return false }
+
+ if (step > zero) start <= x && x < end
+ else start >= x && x > end
+ }
+
+ def inclusive = GenericRange.inclusive(start, end, step)
+}
+
+private[scala] trait RangeToString[T] extends VectorView[T, Vector[T]] {
+ // The default toString() tries to print every element and will exhaust memory
+ // if the Range is unduly large. This interacts poorly with the REPL.
+ override def toString() = {
+ val MAX_PRINT = 512 // some arbitrary value
+ val str = (this take MAX_PRINT).toString
+
+ if (length > MAX_PRINT) str.replaceAll("""\)$""", ", ...)")
+ else str
+ }
+}
+
+object GenericRange {
+ import Numeric._
+ import Ordering._
+
+ // This is very ugly, but modelled on the existing range class for now
+ private class Inclusive[T](start: T, end0: T, step: T)(implicit num: Integral[T], ord: Ordering[T])
+ extends GenericRange(
+ start,
+ if (ord.gt(step, num.zero)) num.plus(end0, num.one) else num.minus(end0, num.one),
+ step)
+ {
+ self =>
+ override def by(step: T): GenericRange[T] = new Inclusive(start, end0, step)
+ }
+
+ def apply[T](start: T, end: T, step: T)(implicit num: Integral[T], ord: Ordering[T]) =
+ new GenericRange(start, end, step)
+
+ def inclusive[T](start: T, end: T, step: T)(implicit num: Integral[T], ord: Ordering[T]): GenericRange[T] =
+ new GenericRange.Inclusive(start, end, step)
+}
+
+class BigIntRange(start: BigInt, end: BigInt, step: BigInt)
+extends GenericRange(start, end, step)(Numeric.BigIntIsIntegral, Ordering.BigInt) {}
+class LongRange(start: Long, end: Long, step: Long)
+extends GenericRange(start, end, step)(Numeric.LongIsIntegral, Ordering.Long) {}
+
+// Illustrating genericity with IntRange, which should have the same behavior
+// as the original Range class. However we leave the original Range
+// indefinitely, for performance and because the compiler seems to bootstrap
+// off it and won't do so with our parameterized version without modifications.
+class IntRange(start: Int, end: Int, step: Int)
+extends GenericRange(start, end, step)(Numeric.IntIsIntegral, Ordering.Int) {}
+
+/** <p>
* The <code>Range</code> class represents integer values in range
* <code>[start;end)</code> with non-zero step value <code>step</code>.
* Sort of acts like a sequence also (supports length and contains).
@@ -28,7 +158,9 @@ import collection.generic.VectorView
* @author Martin Odersky
* @version 2.8
*/
-class Range(val start: Int, val end: Int, val step: Int) extends VectorView[Int, Vector[Int]] {
+class Range(val start: Int, val end: Int, val step: Int)
+extends VectorView[Int, Vector[Int]] with RangeToString[Int]
+{
require(step != 0)
protected def underlying = Vector.empty[Int]
@@ -71,6 +203,7 @@ class Range(val start: Int, val end: Int, val step: Int) extends VectorView[Int,
def inclusive = Range.inclusive(start, end, step)
}
+
object Range {
/** @deprecated use Range.inclusive instead */
class Inclusive(start: Int, end0: Int, step: Int)