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
if
expression, the type is the least upper bound of the two possible branches: if the consequent expression (println("hello")
in this case) has typeA
and the alternative expression ((1, "hi")
) has typeB
, then it is the typeC
such thatA
andB
are both non-strict subtypes ofC
and there is no typeD
which is a strict subtype ofC
whereA
andB
are 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")
isUnit
The type of
(1, "hi")
is aTuple2[Int, String]
Unit
's supertypes areAnyVal
andAny
Tuple2
'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 theif
expression and thus ofb
isAny
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
.