Type decided by expression

var s = if (x > 0) 1 else ()

Does it mean its only during run time we can find what type ‘s’ is?And doesn’t it go against Scala’s statically typed property?

No, Scala infers types at compile time

object Answer {

 val x = 10

 // var s = if (x > 0) 1 else ()

 // var s: Int = if (x > 0) 1 else ()

 // var s: Unit = if (x > 0) 1 else ()

}

/*

===

using var s = if (x > 0) 1 else ()

$ fsc Answer.scala
$ 

the compiler is perfectly happy

===

using var s: Int = if (x > 0) 1 else ()

$ fsc Answer.scala
/opt/home/tmp/Answer.scala:7: error: type mismatch;
 found   : Unit
 required: Int
 var s: Int = if (x > 0) 1 else ()
                                ^
one error found

the compiler provides an appropriate error message

===

using var s: Unit = if (x > 0) 1 else ()

$ fsc Answer.scala
/opt/home/tmp/Answer.scala:9: warning: a pure expression does nothing in statement position
 var s: Unit = if (x > 0) 1 else ()
                          ^
one warning found

The compiler is happy when you, kind of, ignore the inferred type and use Unit instead.
Almost any type is a subtype of Unit

Agreed, a somewhat special warning.


===

Let us try the REPL

$ scala
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_121).
Type in expressions for evaluation. Or try :help.

scala> val x = 10
x: Int = 10

scala> var s = if (x > 0) 1 else ()
s: AnyVal = 1

scala> var s: Int = if (x > 0) 1 else ()
<console>:12: error: type mismatch;
 found   : Unit
 required: Int
       var s: Int = if (x > 0) 1 else ()
                                      ^

scala> var s: Unit = if (x > 0) 1 else ()
<console>:12: warning: a pure expression does nothing in statement position
       var s: Unit = if (x > 0) 1 else ()
                                ^
s: Unit = ()

scala> :quit

Looks like the (compile time) inferred type of 'if (x > 0) 1 else ()' is AnyVal

*/

“Almost any type is a subtype of Unit”…that makes it clear.Thanks.

“Almost any type is a subtype of Unit” is false.

Scala has a concept of “value discarding”, which means that whenever a type of Unit is expected, a value of any other type is accepted. But this doesn’t happen because of subtyping. It happens by substituting () for the discarded value. (Otherwise the types wouldn’t line up.)

You can enable -Ywarn-value-discard if you want the compiler to warn you when this is happening:

% scala -Ywarn-value-discard
Welcome to Scala 2.12.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_162).
Type in expressions for evaluation. Or try :help.

scala> 3: Unit
<console>:12: warning: discarded non-Unit value
       3: Unit
       ^
2 Likes

I fully agree, sorry for the inacurracy … it was more of an intuitive explanation … not a good idea
thx

1 Like