For example I have a class Value and a implicit function convert string to Value:
case class Value(v: String)
implicit def strToValue(s: String): Value = Value(s)
And here is a trait which has a method returns Value:
trait ReturnValue {
def f: Value
}
Because the implicit conversion exists, I can implement method f by just return a String literal:
object Obj1 extends ReturnValue {
override def f: Value = "123"
}
And of course return a variable of type String just works fine:
object Obj2 extends ReturnValue {
override def f: Value = {
val v = Some("123").getOrElse("234")
v
}
}
But when I trying to use the result of Option.getOrElse directly as the return value:
object Obj3 extends ReturnValue {
override def f: Value = Some("123").getOrElse("234") // Compilation error: type mismatch
}
A compilation error occurred:
Error:(23, 50) type mismatch;
found : java.io.Serializable
required: Entry.Value
override def f: Value = Some("123").getOrElse("234") // Compilation error: type mismatch
It seems that type inference here is failed. Type String is not inferred, and then the implicit conversion cannot be matched. (Full file is here)
I have tried other functions which have type parameter, such as "map", they all works perfectly.
Why is the Option.getOrElse so special that type inference failed here?
override def f: Value = Some("123": Value).getOrElse("234")
andoverride def f: Value = None.getOrElse("234")
and evenoverride def f: Value = Some("123").get
. – Sumadef f: Value = Some("123").getOrElse[String]("234")
, to ensure that the conversion is done at the last possible moment. I believe the issue is related to the fact thatgetOrElse
as a call-by-name argument, which must interact wierdly with the type inference and the implicit conversion resolution. – Cyrille Corpet