Reputation: 9761
Why does this code works:
val f: String => Unit = {(_:String) => 2}
//or more succinctly
val f: String => Unit = _ => 2
Clearly the body of my function return an int. However the type expected is Unit
But if i do
implicitly[String <:< Unit]
//Cannot prove that String <:< Unit.
Hence i am a bit confused as to how the cast is happening ? Why is it even allowed in the first place
Upvotes: 0
Views: 289
Reputation: 369458
This is called Value Discarding, see 6.26.1 Value Conversions, sub-section Value Discarding of the Scala Language Specification:
If 𝑒 has some value type and the expected type is
Unit
, 𝑒 is converted to the expected type by embedding it in the term{ 𝑒; () }
.
In other words, your code is compiled as-if you had written
val f: String => Unit = {(_:String) => { 2; () }}
//or more succinctly
val f: String => Unit = _ => { 2; () }
I guess the intention behind this feature is familiarity for programmers coming from imperative programming languages, where it is often possible to discard values.
E.g. in C, it is legal to write
printf("Hello");
and discard the return value, even though printf
returns an int
. This goes together with the idea of expression statements and statement expressions that many imperative programming languages have.
Upvotes: 4
Reputation: 51658
In Scala any type A
can be transformed into type Unit
. It's not subtyping, it's transforming. Like type A
means some possible side effect plus returning A
while Unit
means we disregard return value but keep the side effect.
Upvotes: 1