summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-11-01 16:27:13 +0000
committerPaul Phillips <paulp@improving.org>2010-11-01 16:27:13 +0000
commit9b54520a8c5a4f130a1fabbb0d0e7a3ec9022f41 (patch)
tree254c5a777abd099826873ac5ee686a5452370fdd /src
parent1df37f476926ada63e223abcbe119147b6d693b3 (diff)
downloadscala-9b54520a8c5a4f130a1fabbb0d0e7a3ec9022f41.tar.gz
scala-9b54520a8c5a4f130a1fabbb0d0e7a3ec9022f41.tar.bz2
scala-9b54520a8c5a4f130a1fabbb0d0e7a3ec9022f41.zip
Eliminated duplication among the Rich* wrappers...
Eliminated duplication among the Rich* wrappers, careful not to impact performance on RichInt in particular. Attempted to make Proxy a little bit typier. Proxy creates an asymmetric equals method by design so it's unfixable in that regard, but achieved a minor miracle anyway by making the Rich* wrappers behave symmetrically. Note: said miracle involved having the wrappers extend ScalaNumber in order to induce the special == semantics. This in turn led to implicit conversion conflicts with the boxed types on methods like .intValue(). Resolved by moving the Rich* implicits into LowPriorityImplicits. This of course also removed the intentional ambiguity which prevents primitives from automatically becoming AnyRefs. Solved THAT one by creating dedicated, laser-precise ambiguity creating implicits in Predef which exclude only the AnyRef methods. Although this is admittedly less than elegant, it is still better than it was: this way it is direct and explicit rather than depending upon the "implicit implicit conflict" where the barrier to promotion is intermingled with the definitions of wrapper classes. (See the history of BoxedUnit/RichUnit for a good example of why these concerns require separation.) It's all worth it: assert(intWrapper(5) == 5) assert(5 == intWrapper(5)) assert(5 == (5: java.lang.Integer)) assert((5: java.lang.Integer) == 5) assert((5: java.lang.Integer) == intWrapper(5)) assert(intWrapper(5) == (5: java.lang.Integer)) Review by community.
Diffstat (limited to 'src')
-rw-r--r--src/library/scala/LowPriorityImplicits.scala13
-rw-r--r--src/library/scala/Predef.scala24
-rw-r--r--src/library/scala/Proxy.scala34
-rw-r--r--src/library/scala/math/Numeric.scala12
-rw-r--r--src/library/scala/runtime/RichBoolean.scala11
-rw-r--r--src/library/scala/runtime/RichByte.scala13
-rw-r--r--src/library/scala/runtime/RichChar.scala95
-rw-r--r--src/library/scala/runtime/RichDouble.scala54
-rw-r--r--src/library/scala/runtime/RichFloat.scala36
-rw-r--r--src/library/scala/runtime/RichInt.scala38
-rw-r--r--src/library/scala/runtime/RichLong.scala38
-rw-r--r--src/library/scala/runtime/RichShort.scala13
-rw-r--r--src/library/scala/runtime/ScalaNumberProxy.scala80
13 files changed, 218 insertions, 243 deletions
diff --git a/src/library/scala/LowPriorityImplicits.scala b/src/library/scala/LowPriorityImplicits.scala
index 32bdf7e30d..1b9a65cdaf 100644
--- a/src/library/scala/LowPriorityImplicits.scala
+++ b/src/library/scala/LowPriorityImplicits.scala
@@ -21,6 +21,19 @@ import collection.generic.CanBuildFrom
* @since 2.8
*/
class LowPriorityImplicits {
+ /** We prefer the java.lang.* boxed types to these wrappers in
+ * any potential conflicts. Conflicts do exist because the wrappers
+ * need to implement ScalaNumber in order to have a symmetric equals
+ * method, but that implies implementing java.lang.Number as well.
+ */
+ implicit def byteWrapper(x: Byte) = new runtime.RichByte(x)
+ implicit def shortWrapper(x: Short) = new runtime.RichShort(x)
+ implicit def intWrapper(x: Int) = new runtime.RichInt(x)
+ implicit def charWrapper(c: Char) = new runtime.RichChar(c)
+ implicit def longWrapper(x: Long) = new runtime.RichLong(x)
+ implicit def floatWrapper(x: Float) = new runtime.RichFloat(x)
+ implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x)
+ implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x)
implicit def genericWrapArray[T](xs: Array[T]): WrappedArray[T] =
if (xs ne null) WrappedArray.make(xs) else null
diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala
index bd8f6b6822..2c60a8e8a8 100644
--- a/src/library/scala/Predef.scala
+++ b/src/library/scala/Predef.scala
@@ -199,19 +199,8 @@ object Predef extends LowPriorityImplicits {
// views --------------------------------------------------------------
- implicit def byteWrapper(x: Byte) = new runtime.RichByte(x)
- implicit def shortWrapper(x: Short) = new runtime.RichShort(x)
- implicit def intWrapper(x: Int) = new runtime.RichInt(x)
- implicit def charWrapper(c: Char) = new runtime.RichChar(c)
- implicit def longWrapper(x: Long) = new runtime.RichLong(x)
- implicit def floatWrapper(x: Float) = new runtime.RichFloat(x)
- implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x)
- implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x)
-
implicit def exceptionWrapper(exc: Throwable) = new runtime.RichException(exc)
- // tuple zip views
-
implicit def zipped2ToTraversable[El1, El2](zz: Tuple2[_, _]#Zipped[_, El1, _, El2]): Traversable[(El1, El2)] =
new Traversable[(El1, El2)] {
def foreach[U](f: ((El1, El2)) => U): Unit = zz foreach Function.untupled(f)
@@ -285,6 +274,19 @@ object Predef extends LowPriorityImplicits {
implicit def double2Double(x: Double) = java.lang.Double.valueOf(x)
implicit def boolean2Boolean(x: Boolean) = java.lang.Boolean.valueOf(x)
+ // These next eight implicits exist solely to exclude AnyRef methods from the
+ // eight implicits above so that primitives are not coerced to AnyRefs. They
+ // only create such conflict for AnyRef methods, so the methods on the java.lang
+ // boxed types are unambiguously reachable.
+ implicit def byte2ByteConflict(x: Byte) = new AnyRef
+ implicit def short2ShortConflict(x: Short) = new AnyRef
+ implicit def char2CharacterConflict(x: Char) = new AnyRef
+ implicit def int2IntegerConflict(x: Int) = new AnyRef
+ implicit def long2LongConflict(x: Long) = new AnyRef
+ implicit def float2FloatConflict(x: Float) = new AnyRef
+ implicit def double2DoubleConflict(x: Double) = new AnyRef
+ implicit def boolean2BooleanConflict(x: Boolean) = new AnyRef
+
implicit def Byte2byte(x: java.lang.Byte): Byte = x.byteValue
implicit def Short2short(x: java.lang.Short): Short = x.shortValue
implicit def Character2char(x: java.lang.Character): Char = x.charValue
diff --git a/src/library/scala/Proxy.scala b/src/library/scala/Proxy.scala
index feac5904a5..b7bf8eeef3 100644
--- a/src/library/scala/Proxy.scala
+++ b/src/library/scala/Proxy.scala
@@ -6,24 +6,38 @@
** |/ **
\* */
-
-
package scala
-
/** This class implements a simple proxy that forwards all calls to
- * methods of class <code>Any</code> to another object <code>self</code>.
- * Please note that only those methods can be forwarded that are
- * overridable and public.
+ * the public, non-final methods defined in class "Any" to another
+ * object self. Those methods are:
+ *
+ * def hashCode(): Int
+ * def equals(other: Any): Boolean
+ * def toString(): String
+ *
+ * Note: forwarding methods in this way will most likely create
+ * an asymmetric equals method, which is not generally recommended.
*
* @author Matthias Zenger
* @version 1.0, 26/04/2004
*/
trait Proxy {
def self: Any
- override def hashCode: Int = self.##
- override def equals(that: Any): Boolean =
- if(that == null) false
- else that equals self
+
+ override def hashCode: Int = self.hashCode
+ override def equals(that: Any): Boolean = that match {
+ case null => false
+ case x: Equals => (x canEqual self) && (x equals self)
+ case x => (x equals self)
+ }
override def toString: String = self.toString
}
+
+object Proxy {
+ /** A proxy which exposes the type it is proxying for via a type parameter.
+ */
+ trait Typed[T] extends Proxy {
+ def self: T
+ }
+}
diff --git a/src/library/scala/math/Numeric.scala b/src/library/scala/math/Numeric.scala
index 673461132f..9cf2a15439 100644
--- a/src/library/scala/math/Numeric.scala
+++ b/src/library/scala/math/Numeric.scala
@@ -104,11 +104,10 @@ object Numeric {
}
implicit object LongIsIntegral extends LongIsIntegral with Ordering.LongOrdering
- trait FloatIsFractional extends Fractional[Float] {
+ trait FloatIsConflicted extends Numeric[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
- def div(x: Float, y: Float): Float = x / y
def negate(x: Float): Float = -x
def fromInt(x: Int): Float = x
def toInt(x: Float): Int = x.toInt
@@ -116,7 +115,16 @@ object Numeric {
def toFloat(x: Float): Float = x
def toDouble(x: Float): Double = x
}
+ trait FloatIsFractional extends FloatIsConflicted with Fractional[Float] {
+ def div(x: Float, y: Float): Float = x / y
+ }
+ trait FloatAsIfIntegral extends FloatIsConflicted with Integral[Float] {
+ def quot(x: Float, y: Float): Float = (BigDecimal(x) / BigDecimal(y)).floatValue
+ def rem(x: Float, y: Float): Float = (BigDecimal(x) remainder BigDecimal(y)).floatValue
+ }
implicit object FloatIsFractional extends FloatIsFractional with Ordering.FloatOrdering
+ object FloatAsIfIntegral extends FloatAsIfIntegral with Ordering.FloatOrdering {
+ }
trait DoubleIsConflicted extends Numeric[Double] {
def plus(x: Double, y: Double): Double = x + y
diff --git a/src/library/scala/runtime/RichBoolean.scala b/src/library/scala/runtime/RichBoolean.scala
index bfff5dae94..289f287b19 100644
--- a/src/library/scala/runtime/RichBoolean.scala
+++ b/src/library/scala/runtime/RichBoolean.scala
@@ -10,13 +10,6 @@
package scala.runtime
-
-final class RichBoolean(x: Boolean) extends Proxy with Ordered[Boolean] {
-
- // Proxy.self
- def self: Any = x
-
- // Ordered[Boolean].compare
- def compare (y: Boolean): Int = if (x == y) 0 else if (x) 1 else -1
-
+final class RichBoolean(val self: Boolean) extends OrderedProxy[Boolean] {
+ protected val ord = Ordering[Boolean]
}
diff --git a/src/library/scala/runtime/RichByte.scala b/src/library/scala/runtime/RichByte.scala
index 52ec045217..fc3a75a0b8 100644
--- a/src/library/scala/runtime/RichByte.scala
+++ b/src/library/scala/runtime/RichByte.scala
@@ -6,17 +6,6 @@
** |/ **
\* */
-
-
package scala.runtime
-
-final class RichByte(x: Byte) extends Proxy with Ordered[Byte] {
-
- // Proxy.self
- def self: Any = x
-
- // Ordered[Byte].compare
- def compare (y: Byte): Int = if (x < y) -1 else if (x > y) 1 else 0
-
-}
+final class RichByte(val self: Byte) extends ScalaWholeNumberProxy[Byte] { }
diff --git a/src/library/scala/runtime/RichChar.scala b/src/library/scala/runtime/RichChar.scala
index b8324fa221..675af3aada 100644
--- a/src/library/scala/runtime/RichChar.scala
+++ b/src/library/scala/runtime/RichChar.scala
@@ -6,65 +6,39 @@
** |/ **
\* */
-
-
package scala.runtime
import java.lang.Character
-import collection.immutable.NumericRange
-
-/** <p>
- * For example, in the following code
- * </p>
- * <pre>
- * <b>object</b> test <b>extends</b> Application {
- * Console.println(<chr>'\40'</chr>.isWhitespace)
- * Console.println('\011'.isWhitespace)
- * Console.println('1'.asDigit == 1)
- * Console.println('A'.asDigit == 10)
- * }</pre>
- * <p>
- * the implicit conversions are performed using the predefined view
- * <a href="../Predef$object.html#charWrapper(scala.Char)"
- * target="contentFrame"><code>Predef.charWrapper</code></a>.
- * </p>
- */
-final class RichChar(x: Char) extends Proxy with Ordered[Char] {
-
- // Proxy.self
- def self: Any = x
-
- // Ordered[Char].compare
- def compare (y: Char): Int = if (x < y) -1 else if (x > y) 1 else 0
-
- def asDigit: Int = Character.digit(x, Character.MAX_RADIX)
- def isControl: Boolean = Character.isISOControl(x)
- def isDigit: Boolean = Character.isDigit(x)
- def isLetter: Boolean = Character.isLetter(x)
- def isLetterOrDigit: Boolean = Character.isLetterOrDigit(x)
- def isWhitespace: Boolean = Character.isWhitespace(x)
- def isSpaceChar: Boolean = Character.isSpaceChar(x)
- def isHighSurrogate: Boolean = Character.isHighSurrogate(x)
- def isLowSurrogate: Boolean = Character.isLowSurrogate(x)
- def isSurrogate: Boolean = isHighSurrogate || isLowSurrogate
- def isUnicodeIdentifierStart: Boolean = Character.isUnicodeIdentifierStart(x)
- def isUnicodeIdentifierPart: Boolean = Character.isUnicodeIdentifierPart(x)
- def isIdentifierIgnorable: Boolean = Character.isIdentifierIgnorable(x)
- def isMirrored: Boolean = Character.isMirrored(x)
-
- def isLower: Boolean = Character.isLowerCase(x)
- def isUpper: Boolean = Character.isUpperCase(x)
- def isTitleCase: Boolean = Character.isTitleCase(x)
-
- def toLower: Char = Character.toLowerCase(x)
- def toUpper: Char = Character.toUpperCase(x)
- def toTitleCase: Char = Character.toTitleCase(x)
-
- def getType: Int = Character.getType(x)
- def getNumericValue: Int = Character.getNumericValue(x)
- def getDirectionality: Byte = Character.getDirectionality(x)
- def reverseBytes: Char = Character.reverseBytes(x)
+final class RichChar(val self: Char) extends IntegralProxy[Char] {
+ def asDigit: Int = Character.digit(self, Character.MAX_RADIX)
+
+ def isControl: Boolean = Character.isISOControl(self)
+ def isDigit: Boolean = Character.isDigit(self)
+ def isLetter: Boolean = Character.isLetter(self)
+ def isLetterOrDigit: Boolean = Character.isLetterOrDigit(self)
+ def isWhitespace: Boolean = Character.isWhitespace(self)
+ def isSpaceChar: Boolean = Character.isSpaceChar(self)
+ def isHighSurrogate: Boolean = Character.isHighSurrogate(self)
+ def isLowSurrogate: Boolean = Character.isLowSurrogate(self)
+ def isSurrogate: Boolean = isHighSurrogate || isLowSurrogate
+ def isUnicodeIdentifierStart: Boolean = Character.isUnicodeIdentifierStart(self)
+ def isUnicodeIdentifierPart: Boolean = Character.isUnicodeIdentifierPart(self)
+ def isIdentifierIgnorable: Boolean = Character.isIdentifierIgnorable(self)
+ def isMirrored: Boolean = Character.isMirrored(self)
+
+ def isLower: Boolean = Character.isLowerCase(self)
+ def isUpper: Boolean = Character.isUpperCase(self)
+ def isTitleCase: Boolean = Character.isTitleCase(self)
+
+ def toLower: Char = Character.toLowerCase(self)
+ def toUpper: Char = Character.toUpperCase(self)
+ def toTitleCase: Char = Character.toTitleCase(self)
+
+ def getType: Int = Character.getType(self)
+ def getNumericValue: Int = Character.getNumericValue(self)
+ def getDirectionality: Byte = Character.getDirectionality(self)
+ def reverseBytes: Char = Character.reverseBytes(self)
// Java 5 Character methods not added:
//
@@ -81,15 +55,4 @@ final class RichChar(x: Char) extends Proxy with Ordered[Char] {
def isLowerCase: Boolean = isLower
@deprecated("Use ch.isUpper instead")
def isUpperCase: Boolean = isUpper
-
- /** Create a <code>[Char]</code> over the characters from 'x' to 'limit' - 1
- */
- def until(limit: Char): NumericRange[Char] =
- new NumericRange.Exclusive(x, limit, 1.toChar)
-
- /** Create a <code>IndexedSeqView[Char]</code> over the characters from 'x' to 'limit'
- */
- def to(limit: Char): NumericRange[Char] =
- new NumericRange.Inclusive(x, limit, 1.toChar)
-
}
diff --git a/src/library/scala/runtime/RichDouble.scala b/src/library/scala/runtime/RichDouble.scala
index 64976acb12..607bde1fb5 100644
--- a/src/library/scala/runtime/RichDouble.scala
+++ b/src/library/scala/runtime/RichDouble.scala
@@ -6,62 +6,34 @@
** |/ **
\* */
-
-
package scala.runtime
-import scala.collection.immutable.{Range, NumericRange}
-
-final class RichDouble(x: Double) extends Proxy with Ordered[Double] {
- // Proxy.self
- def self: Any = x
-
- def compare(y: Double): Int = java.lang.Double.compare(x, y)
-
- def min(y: Double): Double = math.min(x, y)
- def max(y: Double): Double = math.max(x, y)
- def abs: Double = math.abs(x)
+final class RichDouble(val self: Double) extends FractionalProxy[Double] {
+ protected val integralNum = Numeric.DoubleAsIfIntegral
- def round: Long = math.round(x)
- def ceil: Double = math.ceil(x)
- def floor: Double = math.floor(x)
-
- /** See <code>BigDecimal.until</code>. */
- def until(end: Double): Range.Partial[Double, NumericRange[Double]] =
- new Range.Partial(until(end, _))
-
- /** See <code>BigDecimal.until</code>. */
- def until(end: Double, step: Double): NumericRange[Double] =
- Range.Double(x, end, step)
-
- /** See <code>BigDecimal.to</code>. */
- def to(end: Double): Range.Partial[Double, NumericRange[Double]] =
- new Range.Partial(to(end, _))
-
- /** See <code>BigDecimal.to</code>. */
- def to(end: Double, step: Double): NumericRange[Double] =
- Range.Double.inclusive(x, end, step)
+ def round: Long = math.round(self)
+ def ceil: Double = math.ceil(self)
+ def floor: Double = math.floor(self)
/** Converts an angle measured in degrees to an approximately equivalent
* angle measured in radians.
*
* @param x an angle, in degrees
- * @return the measurement of the angle <code>x</code> in radians.
+ * @return the measurement of the angle x in radians.
*/
- def toRadians: Double = math.toRadians(x)
+ def toRadians: Double = math.toRadians(self)
/** Converts an angle measured in radians to an approximately equivalent
* angle measured in degrees
*
* @param x angle, in radians
- * @return the measurement of the angle <code>x</code> in degrees.
+ * @return the measurement of the angle x in degrees.
*/
- def toDegrees: Double = math.toDegrees(x)
+ def toDegrees: Double = math.toDegrees(self)
// isNaN is provided by the implicit conversion to java.lang.Double
- // def isNaN: Boolean = java.lang.Double.isNaN(x)
- def isInfinity: Boolean = java.lang.Double.isInfinite(x)
- def isPosInfinity: Boolean = isInfinity && x > 0.0
- def isNegInfinity: Boolean = isInfinity && x < 0.0
-
+ // def isNaN: Boolean = java.lang.Double.isNaN(self)
+ def isInfinity: Boolean = java.lang.Double.isInfinite(self)
+ def isPosInfinity: Boolean = isInfinity && self > 0.0
+ def isNegInfinity: Boolean = isInfinity && self < 0.0
}
diff --git a/src/library/scala/runtime/RichFloat.scala b/src/library/scala/runtime/RichFloat.scala
index e8e351bdaa..8a4ab13c19 100644
--- a/src/library/scala/runtime/RichFloat.scala
+++ b/src/library/scala/runtime/RichFloat.scala
@@ -6,27 +6,14 @@
** |/ **
\* */
-
-
package scala.runtime
+final class RichFloat(val self: Float) extends FractionalProxy[Float] {
+ protected val integralNum = Numeric.FloatAsIfIntegral
-final class RichFloat(x: Float) extends Proxy with Ordered[Float] {
-
- // Proxy.self
- def self: Any = x
-
- // Ordered[Float].compare
- //def compare(y: Float): Int = if (x < y) -1 else if (x > y) 1 else 0
- def compare(y: Float): Int = java.lang.Float.compare(x, y)
-
- def min(y: Float) = math.min(x, y)
- def max(y: Float) = math.max(x, y)
- def abs: Float = math.abs(x)
-
- def round: Int = math.round(x)
- def ceil: Float = math.ceil(x).toFloat
- def floor: Float = math.floor(x).toFloat
+ def round: Int = math.round(self)
+ def ceil: Float = math.ceil(self).toFloat
+ def floor: Float = math.floor(self).toFloat
/** Converts an angle measured in degrees to an approximately equivalent
* angle measured in radians.
@@ -34,7 +21,7 @@ final class RichFloat(x: Float) extends Proxy with Ordered[Float] {
* @param x an angle, in degrees
* @return the measurement of the angle <code>x</code> in radians.
*/
- def toRadians: Float = math.toRadians(x).toFloat
+ def toRadians: Float = math.toRadians(self).toFloat
/** Converts an angle measured in radians to an approximately equivalent
* angle measured in degrees.
@@ -42,12 +29,11 @@ final class RichFloat(x: Float) extends Proxy with Ordered[Float] {
* @param x angle, in radians
* @return the measurement of the angle <code>x</code> in degrees.
*/
- def toDegrees: Float = math.toDegrees(x).toFloat
+ def toDegrees: Float = math.toDegrees(self).toFloat
// isNaN is provided by the implicit conversion to java.lang.Float
- // def isNaN: Boolean = java.lang.Float.isNaN(x)
- def isInfinity: Boolean = java.lang.Float.isInfinite(x)
- def isPosInfinity: Boolean = isInfinity && x > 0.0f
- def isNegInfinity: Boolean = isInfinity && x < 0.0f
-
+ // def isNaN: Boolean = java.lang.Float.isNaN(self)
+ def isInfinity: Boolean = java.lang.Float.isInfinite(self)
+ def isPosInfinity: Boolean = isInfinity && self > 0.0f
+ def isNegInfinity: Boolean = isInfinity && self < 0.0f
}
diff --git a/src/library/scala/runtime/RichInt.scala b/src/library/scala/runtime/RichInt.scala
index c5ed5df07c..8ba5685922 100644
--- a/src/library/scala/runtime/RichInt.scala
+++ b/src/library/scala/runtime/RichInt.scala
@@ -7,32 +7,28 @@
\* */
-
package scala.runtime
-import collection.immutable.Range
-
-
-final class RichInt(val start: Int) extends Proxy with Ordered[Int] {
-
- // Proxy
- def self: Any = start
+import scala.collection.immutable.Range
- // Ordered[Int]
- def compare(that: Int): Int = if (start < that) -1 else if (start > that) 1 else 0
+// Note that this does not implement IntegralProxy[Int] so that it can return
+// the Int-specific Range class from until/to.
+final class RichInt(val self: Int) extends ScalaNumberProxy[Int] with RangedProxy[Int] {
+ type ResultWithoutStep = Range
+ def isWhole() = true
- def until(end: Int): Range = Range(start, end)
- def until(end: Int, step: Int): Range = Range(start, end, step)
+ def until(end: Int): Range = Range(self, end)
+ def until(end: Int, step: Int): Range = Range(self, end, step)
- /** like <code>until</code>, but includes the last index */
- def to(end: Int): Range.Inclusive = Range.inclusive(start, end)
- def to(end: Int, step: Int): Range.Inclusive = Range.inclusive(start, end, step)
+ /** like `until`, but includes the last index */
+ def to(end: Int): Range.Inclusive = Range.inclusive(self, end)
+ def to(end: Int, step: Int): Range.Inclusive = Range.inclusive(self, end, step)
- def min(that: Int): Int = if (start < that) start else that
- def max(that: Int): Int = if (start > that) start else that
- def abs: Int = if (start < 0) -start else start
+ override def min(that: Int): Int = if (self < that) self else that
+ override def max(that: Int): Int = if (self > that) self else that
+ override def abs: Int = if (self < 0) -self else self
- def toBinaryString: String = java.lang.Integer.toBinaryString(start)
- def toHexString: String = java.lang.Integer.toHexString(start)
- def toOctalString: String = java.lang.Integer.toOctalString(start)
+ def toBinaryString: String = java.lang.Integer.toBinaryString(self)
+ def toHexString: String = java.lang.Integer.toHexString(self)
+ def toOctalString: String = java.lang.Integer.toOctalString(self)
}
diff --git a/src/library/scala/runtime/RichLong.scala b/src/library/scala/runtime/RichLong.scala
index 82e2c77ef7..807929aa6d 100644
--- a/src/library/scala/runtime/RichLong.scala
+++ b/src/library/scala/runtime/RichLong.scala
@@ -6,40 +6,10 @@
** |/ **
\* */
-
-
package scala.runtime
-import scala.collection.immutable.{Range, NumericRange}
-
-final class RichLong(x: Long) extends Proxy with Ordered[Long] {
-
- // Proxy.self
- def self: Any = x
-
- // Ordered[Long].compare
- def compare(y: Long): Int = if (x < y) -1 else if (x > y) 1 else 0
-
- /** Create a NumericRange[Long] in range <code>[start;end)</code>
- * with the specified step, where start is the target Long.
- *
- * @param end the end value of the range (exclusive)
- * @param step the distance between elements (defaults to 1)
- * @return the range
- */
- def until(end: Long, step: Long = 1L): NumericRange.Exclusive[Long] = Range.Long(x, end, step)
-
- def until(end: Long): NumericRange.Exclusive[Long] = Range.Long(x, end, 1l)
-
- /** Like until, but inclusive of the end value.
- */
- def to(end: Long, step: Long = 1L): NumericRange.Inclusive[Long] = Range.Long.inclusive(x, end, step)
-
- def min(y: Long): Long = if (x < y) x else y
- def max(y: Long): Long = if (x > y) x else y
- def abs: Long = if (x < 0) -x else x
-
- def toBinaryString: String = java.lang.Long.toBinaryString(x)
- def toHexString: String = java.lang.Long.toHexString(x)
- def toOctalString: String = java.lang.Long.toOctalString(x)
+final class RichLong(val self: Long) extends IntegralProxy[Long] {
+ def toBinaryString: String = java.lang.Long.toBinaryString(self)
+ def toHexString: String = java.lang.Long.toHexString(self)
+ def toOctalString: String = java.lang.Long.toOctalString(self)
}
diff --git a/src/library/scala/runtime/RichShort.scala b/src/library/scala/runtime/RichShort.scala
index 0fa34b27c4..51214ac13e 100644
--- a/src/library/scala/runtime/RichShort.scala
+++ b/src/library/scala/runtime/RichShort.scala
@@ -6,17 +6,6 @@
** |/ **
\* */
-
-
package scala.runtime
-
-final class RichShort(start: Short) extends Proxy with Ordered[Short] {
-
- // Proxy.self
- def self: Any = start
-
- // Ordered[Short].compare
- def compare(that: Short): Int = if (start < that) -1 else if (start > that) 1 else 0
-
-}
+final class RichShort(val self: Short) extends ScalaWholeNumberProxy[Short] { }
diff --git a/src/library/scala/runtime/ScalaNumberProxy.scala b/src/library/scala/runtime/ScalaNumberProxy.scala
new file mode 100644
index 0000000000..42d65ba388
--- /dev/null
+++ b/src/library/scala/runtime/ScalaNumberProxy.scala
@@ -0,0 +1,80 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2010, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.runtime
+
+import scala.collection.{ mutable, immutable }
+import math.ScalaNumericConversions
+import immutable.NumericRange
+import Proxy.Typed
+
+/** Base classes for the Rich* wrappers of the primitive types.
+ * As with all classes in scala.runtime.*, this is not a supported API.
+ *
+ * @author Paul Phillips
+ * @version 2.9
+ * @since 2.9
+ */
+abstract class ScalaNumberProxy[T: Numeric] extends ScalaNumericConversions with Typed[T] with OrderedProxy[T] {
+ private val num = implicitly[Numeric[T]]
+ protected val ord: Ordering[T] = num
+
+ def underlying() = self.asInstanceOf[AnyRef]
+ def doubleValue() = num.toDouble(self)
+ def floatValue() = num.toFloat(self)
+ def longValue() = num.toLong(self)
+ def intValue() = num.toInt(self)
+
+ def min(that: T): T = num.min(self, that)
+ def max(that: T): T = num.max(self, that)
+ def abs = num.abs(self)
+ def signum = num.signum(self)
+}
+abstract class ScalaWholeNumberProxy[T: Numeric] extends ScalaNumberProxy[T] {
+ def isWhole() = true
+}
+abstract class IntegralProxy[T : Integral] extends ScalaWholeNumberProxy[T] with RangedProxy[T] {
+ private lazy val num = implicitly[Integral[T]]
+ type ResultWithoutStep = NumericRange[T]
+
+ def until(end: T): NumericRange.Exclusive[T] = NumericRange(self, end, num.one)
+ def until(end: T, step: T): NumericRange.Exclusive[T] = NumericRange(self, end, step)
+ def to(end: T): NumericRange.Inclusive[T] = NumericRange.inclusive(self, end, num.one)
+ def to(end: T, step: T): NumericRange.Inclusive[T] = NumericRange.inclusive(self, end, step)
+}
+abstract class FractionalProxy[T : Fractional] extends ScalaNumberProxy[T] with RangedProxy[T] {
+ def isWhole() = false
+
+ /** In order to supply predictable ranges, we require an Integral[T] which provides
+ * us with discrete operations on the (otherwise fractional) T. See Numeric.DoubleAsIfIntegral
+ * for an example.
+ */
+ protected implicit def integralNum: Integral[T]
+ private lazy val num = implicitly[Fractional[T]]
+ type ResultWithoutStep = Range.Partial[T, NumericRange[T]]
+
+ def until(end: T): ResultWithoutStep = new Range.Partial(NumericRange(self, end, _))
+ def until(end: T, step: T): NumericRange.Exclusive[T] = NumericRange(self, end, step)
+ def to(end: T): ResultWithoutStep = new Range.Partial(NumericRange.inclusive(self, end, _))
+ def to(end: T, step: T): NumericRange.Inclusive[T] = NumericRange.inclusive(self, end, step)
+}
+
+trait OrderedProxy[T] extends Typed[T] with Ordered[T] {
+ protected def ord: Ordering[T]
+
+ def compare(y: T) = ord.compare(self, y)
+}
+trait RangedProxy[T] extends Typed[T] {
+ type ResultWithoutStep
+
+ def until(end: T): ResultWithoutStep
+ def until(end: T, step: T): immutable.IndexedSeq[T]
+ def to(end: T): ResultWithoutStep
+ def to(end: T, step: T): immutable.IndexedSeq[T]
+}
+