在Scala中,为什么我可以在这里使用`Unit`作为返回类型?

Han*_*Sun 3 java types functional-programming scala type-inference

代码如下:

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));
Run Code Online (Sandbox Code Playgroud)

上面的所有三个表达式都在REPL中工作(有一些警告),但它们看起来有点令人困惑.

在第一个表达式中,f's返回类型是Unit,AnyVal但是不是Supertype 的子类型Int,因此,我无法理解为什么1可以用作返回值.

在第二个表达式中,_=>2也使用2而不是Unit作为返回值,它与定义冲突.

在第三个表达式中,_=> List(1,2)甚至使用List子类型AnyRef作为返回值,但REPL仍然没有抱怨这个..

有没有人有关于为什么Unit可以容忍非子类型转换的想法?谢谢!

Ben*_*ich 13

在这种情况下,Scala会自动插入()(单例Unit值)以使类型检查工作.所以你所拥有的相当于:

def f(x:Int => Unit):Unit = { 1; () }
Run Code Online (Sandbox Code Playgroud)

这在Scala中被称为"价值丢弃".从规格:

价值丢弃

如果e具有某种值类型且期望的类型是Unit,e则通过将其嵌入到术语中而将其转换为期望的类型 { e; () }

与许多编程语言一样,这意味着只是"抛弃"表达式的返回值.这允许您创建Unit仅使用表达式的副作用的类型方法.