which isn’t even listed in Scaladoc. Same for Ordering. Scaladoc there just says
You can import scala.math.Ordering.Implicits to gain access to other implicit orderings
What are arguments against adding these implicits to Predef? I can think of 2:
Not wanting Predef to depend on scala.math. This doesn’t seem strong to me, since it already depends on scala.collection.immutable and on scala.reflect.
Would it break any existing programs? I thought there could be a conflict because the implicits are also defined on the Numeric/Orderinginstances, but I tried
I don’t think you’re missing much. There’s some general resistance against putting too much stuff into Predef, especially implicits which will then always be in scope for everybody. Historically a lot of stuff was put in there, but now the trend is rather to move stuff out of Predef if possible. But I don’t know why those implicits weren’t added to Predef in the good old days when it wasn’t frowned upon yet…
The good news is that if the new extension methods mechanism of dotty gets accepted, the Right Thing will happen by default without having to put everything in Predef:
scala> trait Ord[T] {
| def (self: T) < (other: T): Boolean
| }
// defined trait Ord
scala> implicit object StringOrd extends Ord[String] {
| def (self: String) < (other: String) = self.compare(other) < 0
| }
// defined object StringOrd
scala> def isLT[A: Ord](a: A, b: A) = a < b
def isLT[A](a: A, b: A)(implicit evidence$1: Ord[A]): Boolean
scala> isLT("bar", "foo")
val res1: Boolean = true
The basic answer to your question is, people more or less agree nowadays that implicit conversions, especially ops-style stuff which add ‘syntactic sugar’ operations to generic methods, should be imported explicitly. We don’t want to pay the import tax to get the actual implicit instances, but we do to get the operations.
So, given this philosophy, I more or less agree with what’s going on here, although I do think it’s a bit more complex than was really necessary. I mean, I get why all those implicits were defined as traits and then as instance objects, but I still think it’s overkill. And there was just no need to create a separate Implicits object just to house a single implicit method, which should have been an implicit class in the first place to provide the same functionality.
So you would have been able to do this:
import scala.math.Numeric.Ops
...
… Where Ops would be the implicit class that provides the operators.
This actually conveys a useful meaning, it actually reads like a meaningful sentence. With the current style you see you’re importing Numeric implicits but it’s kinda hard to understand why you’d need to do that from the naming alone, because the implicit instances should already be in scope.