I don't understand the apparent contradictory behavior I'm seeing in the following code (Scala 2.9):
class Pimp1(val x : Double) {
def pluss(that : Pimp1) = x + that.x
def <(that : Pimp1) = x < that.x
}
object Pimp1 {
implicit def d2pimp(d : Double) = new Pimp1(d)
implicit def d2pimp(od : Option[Double]) = new Pimp1(od.get)
}
object Scratch2 extends App {
import Pimp1._
5.0.pluss(Some(5.0))
5.0 < Some(5.0)
}
The line '5.0.pluss(Some(5.0))' compiles, but the line after it does not compile with the following error message:
overloaded method value < with alternatives: (x: Double)Boolean (x: Float)Boolean (x: Long)Boolean (x: Int)Boolean (x: Char)Boolean (x: Short)Boolean (x: Byte)Boolean cannot be applied to (Some[Double])
If I add explicit < operator to the Pimp class that takes an Option[Double]:
def <(that : Option[Double]) = x < that.get
Everything compiles fine.
Now, the way I understand Scala implicit conversion rules, this makes perfect sense:
- The compiler understands that there's no '<' operator on Double that accepts Option[Double]
- It considers the implicit conversion to Pimp1.
- If Pimp1 has a suitable operator, it works, otherwise, it generates an error.
- Importantly, this demonstrates that the compiler does not consider applying a second (available) implicit conversion, from Option[Double] to Pimp.
This is how I expected things to work.
However, this seems to be contradicted by the first example, where:
- The compiler sees that there's no pluss method on Double.
- The compiler tries the implicit conversion to Pimp, which does have such a method.
- However, in order to make the operator work, the compiler has to apply a second implicit conversion, on the argument, to convert it to Pimp.
According to the logic above, this should not compile, but it does. Do the implicit conversion rules treat non-existing methods and non-matching methods differently?