In Scala, why can I use `Unit` as return type here?

懵懂的女人 提交于 2019-12-12 16:17:06

问题


The codes are below:

scala> def f(x:Int => Unit):Unit = 1
<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
       def f(x:Int => Unit):Unit = 1
                                   ^
f: (x: Int => Unit)Unit

scala> f(_=>2);
<console>:9: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
              f(_=>2);
                   ^

scala> f(_=>List(1,2));

All three expressions above worked in REPL(with some warnings), but they look a bit confusing..

In the first expression, f's return type is Unit, which is the subtype of AnyVal but not the Supertype of Int, therefore, I can't understand why 1 can be used as the returned value.

In the second expression, _=>2 also used 2 instead of Unit as the returned value, which conflicts with the definition.

In the third expression, _=> List(1,2) even uses List, subtype of AnyRef as the returned value, but the REPL still doesn't complain about this..

Does anyone have ideas about why Unit can tolerate the non-subtype type conversion here? Thanks!


回答1:


Scala will automatically insert () (the singleton Unit value) in this case to make the typechecking work. So what you have is equivalent to:

def f(x:Int => Unit):Unit = { 1; () }

This is known as "value discarding" in Scala. From the spec:

Value Discarding

If e has some value type and the expected type is Unit, e is converted to the expected type by embedding it in the term { e; () }

Like in many programming languages, this is meant to facilitate just "throwing out" the return value of the expression. This allows you to make a method of type Unit that only uses the side effects of an expression.




回答2:


Check implicit conversions section in SLS

ValueDiscarding. If e has some value type and the expected type is Unit, e is converted to the expected type by embedding it in the term {e; () }.




回答3:


In addition to the answer of Ben Reich:

Conceptually, in Scala the type Unit is the super type of every other type. Therefore, every value, including Int, is assignable to Unit. Effectively, if used as a return type of a method, the compiler will throw away the result value, giving the method the JVM/Java void type.

Nothing is the exact opposite, by the way: Conceptually, it is a subtype of every other type. Since no instance of Nothing exists, no instance of any other type can therefore be assignment compatible with Nothing.

Java's void somehow is an incomplete mix of both of those.



来源:https://stackoverflow.com/questions/28564324/in-scala-why-can-i-use-unit-as-return-type-here

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!