From f23af514b8e3d431a6cb2f701df1a9a7c7c0fbcd Mon Sep 17 00:00:00 2001 From: extempore Date: Tue, 15 Mar 2011 20:41:57 +0000 Subject: [PATCH] Leveraged having a place to put some useful implicits which we sensibly are reluctant to introduce in the default scope. The test case pretty much sums it up. import Ordering.Implicits._ import Numeric.Implicits._ def f1[T: Numeric](x: T, y: T, z: T) = x + y + z def f2[T: Ordering](x: T, y: T, z: T) = if (x < y) (z > y) else (x < z) No review. git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@24468 5e8d7ff9-d8ef-0310-90f0-a4852d11357a --- src/library/scala/math/Fractional.scala | 2 - src/library/scala/math/Numeric.scala | 14 ++- src/library/scala/math/Ordering.scala | 112 +++++++++++------------- test/files/pos/implicit-infix-ops.scala | 7 ++ 4 files changed, 71 insertions(+), 64 deletions(-) create mode 100644 test/files/pos/implicit-infix-ops.scala diff --git a/src/library/scala/math/Fractional.scala b/src/library/scala/math/Fractional.scala index 31c49269a..1532528c1 100644 --- a/src/library/scala/math/Fractional.scala +++ b/src/library/scala/math/Fractional.scala @@ -6,8 +6,6 @@ ** |/ ** \* */ - - package scala.math /** diff --git a/src/library/scala/math/Numeric.scala b/src/library/scala/math/Numeric.scala index f59b32746..5c760f1b7 100644 --- a/src/library/scala/math/Numeric.scala +++ b/src/library/scala/math/Numeric.scala @@ -6,14 +6,24 @@ ** |/ ** \* */ - - package scala.math /** * @since 2.8 */ object Numeric { + trait ExtraImplicits { + /** These implicits create conversions from a value for which an implicit Numeric + * exists to the inner class which creates infix operations. Once imported, you + * can write methods as follows: + * {{{ + * def plus[T: Numeric](x: T, y: T) = x + y + * }}} + */ + implicit def infixNumericOps[T](x: T)(implicit num: Numeric[T]): Numeric[T]#Ops = new num.Ops(x) + } + object Implicits extends ExtraImplicits { } + trait BigIntIsIntegral extends Integral[BigInt] { def plus(x: BigInt, y: BigInt): BigInt = x + y def minus(x: BigInt, y: BigInt): BigInt = x - y diff --git a/src/library/scala/math/Ordering.scala b/src/library/scala/math/Ordering.scala index c9eee447f..874670d50 100644 --- a/src/library/scala/math/Ordering.scala +++ b/src/library/scala/math/Ordering.scala @@ -6,35 +6,25 @@ ** |/ ** \* */ - - package scala.math import java.util.Comparator /** A trait for representing total orderings. It is important to * distinguish between a type that has a total order and a representation - * of total ordering on some type. This trait is for representing the - * latter. + * of total ordering on some type. This trait is for the latter. + * + * A [[http://en.wikipedia.org/wiki/Total_order|total ordering]] + * is a binary relation on a type `T` that is also an equivalence relation + * and partial ordering on values of type `T`. This relation is exposed as + * the `compare` method of the `Ordering` trait. * - * A total ordering - * is a binary relation on a type T that is also an equivalence relation - * and partial ordering on values of type T. This relation is exposed as - * the compare method of the Ordering trait. * This relation must be: - * + {{{ + reflexive: x == x + antisymmetric: if x <= y && y <= x, then x == y + transitive: if x <= y && y <= z, then x <= z + }}} * * @author Geoffrey Washburn * @version 0.9.5, 2008-04-15 @@ -46,36 +36,31 @@ trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializabl /** An Ordering is defined at all x and y. */ def tryCompare(x: T, y: T) = Some(compare(x, y)) - /** Returns a negative integer iff x comes before - * y in the ordering, returns 0 iff x - * is the same in the ordering as y, and returns a - * positive number iff x comes after - * y in the ordering. + /** Returns a negative integer iff `x` comes before + * `y` in the ordering, returns 0 iff `x` + * is the same in the ordering as `y`, and returns a + * positive number iff `x` comes after + * `y` in the ordering. */ def compare(x: T, y: T): Int - /** Returns true iff x comes before - * y in the ordering. + /** @return true iff `x` comes before `y` in the ordering, or is equal to `y`. */ override def lteq(x: T, y: T): Boolean = compare(x, y) <= 0 - /** Returns true iff y comes before - * x in the ordering. + /** @return true iff `x` comes after `y` in the ordering, or is equal to `y`. */ override def gteq(x: T, y: T): Boolean = compare(x, y) >= 0 - /** Returns true iff x comes before - * y in the ordering and is not the same as y. + /** @return true iff `x` comes before `y` in the ordering, and is not equal to `y`. */ override def lt(x: T, y: T): Boolean = compare(x, y) < 0 - /** Returns true iff y comes before - * x in the ordering and is not the same as x. + /** @return true iff `y` comes before `x` in the ordering, and is not equal to `x`. */ override def gt(x: T, y: T): Boolean = compare(x, y) > 0 - /** Returns true iff x is equivalent to - * y in the ordering. + /** @return true iff `x` is equivalent to `y` in the ordering. */ override def equiv(x: T, y: T): Boolean = compare(x, y) == 0 @@ -85,7 +70,7 @@ trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializabl /** Returns the argument which comes earlier in the ordering. */ def min(x: T, y: T): T = if (lteq(x, y)) x else y - override def reverse: Ordering[T] = new Ordering[T]{ + override def reverse: Ordering[T] = new Ordering[T] { override def reverse = outer def compare(x: T, y: T) = outer.compare(y, x) } @@ -107,26 +92,6 @@ trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializabl implicit def mkOrderingOps(lhs: T): Ops = new Ops(lhs) } -trait ExtraOrderingImplicits { - /** Not in the standard scope due to the potential for divergence: - * For instance implicitly[Ordering[Any]] diverges in its presence. - */ - implicit def SeqDerived[CC[X] <: collection.Seq[X], T](implicit ord: Ordering[T]): Ordering[CC[T]] = - new Ordering[CC[T]] { - def compare(x: CC[T], y: CC[T]): Int = { - val xe = x.iterator - val ye = y.iterator - - while (xe.hasNext && ye.hasNext) { - val res = ord.compare(xe.next, ye.next) - if (res != 0) return res - } - - Ordering.Boolean.compare(xe.hasNext, ye.hasNext) - } - } -} - trait LowPriorityOrderingImplicits { /** This would conflict with all the nice implicit Orderings * available, but thanks to the magic of prioritized implicits @@ -145,12 +110,39 @@ trait LowPriorityOrderingImplicits { object Ordering extends LowPriorityOrderingImplicits { def apply[T](implicit ord: Ordering[T]) = ord + trait ExtraImplicits { + /** Not in the standard scope due to the potential for divergence: + * For instance implicitly[Ordering[Any]] diverges in its presence. + */ + implicit def seqDerivedOrdering[CC[X] <: collection.Seq[X], T](implicit ord: Ordering[T]): Ordering[CC[T]] = + new Ordering[CC[T]] { + def compare(x: CC[T], y: CC[T]): Int = { + val xe = x.iterator + val ye = y.iterator + + while (xe.hasNext && ye.hasNext) { + val res = ord.compare(xe.next, ye.next) + if (res != 0) return res + } + + Ordering.Boolean.compare(xe.hasNext, ye.hasNext) + } + } + + /** This implicit creates a conversion from any value for which an implicit Ordering + * exists to the class which creates infix operations. With it imported, you can write + * methods as follows: + * {{{ + * def lessThen[T: Ordering](x: T, y: T) = x < y + * }}} + */ + implicit def infixOrderingOps[T](x: T)(implicit ord: Ordering[T]): Ordering[T]#Ops = new ord.Ops(x) + } + /** An object for implicits which for one reason or another we * aren't ready to put in the default scope. */ - object Implicits extends ExtraOrderingImplicits { - - } + object Implicits extends ExtraImplicits { } def fromLessThan[T](cmp: (T, T) => Boolean): Ordering[T] = new Ordering[T] { def compare(x: T, y: T) = if (cmp(x, y)) -1 else if (cmp(y, x)) 1 else 0 diff --git a/test/files/pos/implicit-infix-ops.scala b/test/files/pos/implicit-infix-ops.scala new file mode 100644 index 000000000..2dbd76bb3 --- /dev/null +++ b/test/files/pos/implicit-infix-ops.scala @@ -0,0 +1,7 @@ +object Test { + import Ordering.Implicits._ + import Numeric.Implicits._ + + def f1[T: Numeric](x: T, y: T, z: T) = x + y + z + def f2[T: Ordering](x: T, y: T, z: T) = if (x < y) (z > y) else (x < z) +}