val a=10; val b=if(a==5) println("hello") else (1,"hi")
What will be return type inferred in this case? And How?
CodePudding user response:
Presumably you're asking for the type of b, which in this case is Any.
if (a == 5) println("hello") else (1, "hi")
gets typed as follows:
For an
ifexpression, the type is the least upper bound of the two possible branches: if the consequent expression (println("hello")in this case) has typeAand the alternative expression ((1, "hi")) has typeB, then it is the typeCsuch thatAandBare both non-strict subtypes ofCand there is no typeDwhich is a strict subtype ofCwhereAandBare non-strict subtypes ofD(non-strict means that we can consider a type to be a subtype of itself; strict means we can't).The type of
println("hello")isUnitThe type of
(1, "hi")is aTuple2[Int, String]Unit's supertypes areAnyValandAnyTuple2's supertypes areSerializable,Product2[Int, String],Product,Equals,AnyRef, andAny(technically,Product2's andTuple2's covariance means that there are some more supertypes (e.g.Tuple2[AnyVal, String],Tuple2[Int, AnyRef],Tuple2[Any, Any]), but those don't end up being relevant here)The least-upper-bound is therefore
Any, so the type of theifexpression and thus ofbisAny
You can demonstrate this in a REPL, e.g. sbt console
scala> :paste
// Entering paste mode (ctrl-D to finish)
val a=10; val b=if(a==5) println("hello") else (1,"hi")
// Exiting paste mode, now interpreting.
a: Int = 10
b: Any = (1,hi)
Note that even though the predicate a == 5 will never be true and thus the consequent branch will never be taken, the typer does not take that into account.
Note also that if you had a method with that body:
def someMethod = {
val a = 10
val b = if(a==5) println("hello") else (1,"hi")
}
The result type of that method would be Unit, because the result type is the type of the last expression in the method and an assignment (being a side-effect) has the type Unit.
