【问题标题】:In Scala, why can I use `Unit` as return type here?在 Scala 中,为什么我可以在这里使用 `Unit` 作为返回类型?
【发布时间】:2015-04-18 07:34:20
【问题描述】:

代码如下:

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));

上面所有三个表达式都在 REPL 中工作(带有一些警告),但它们看起来有点混乱..

在第一个表达式中,f 的返回类型是Unit,它是AnyVal 的子类型而不是Int 的超类型,因此,我不明白为什么1 可以是用作返回值。

第二个表达式中_=&gt;2也使用2而不是Unit作为返回值,与定义冲突。

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

有人知道为什么Unit 可以容忍这里的非子类型转换吗?谢谢!

【问题讨论】:

  • 请注意,您可以使用-Ywarn-value-discard 收到警告。

标签: java scala types functional-programming type-inference


【解决方案1】:

在这种情况下,Scala 将自动插入 ()(单例 Unit 值)以进行类型检查。所以你所拥有的就相当于:

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

这在 Scala 中称为“值丢弃”。来自spec

价值丢弃

如果e 有某个值类型并且预期的类型是Unit,则e 通过嵌入到术语中来转换为预期的类型 { e; () }

与许多编程语言一样,这是为了方便“丢弃”表达式的返回值。这允许您创建一个 Unit 类型的方法,它只使用表达式的副作用。

【讨论】:

    【解决方案2】:

    检查 SLS 中的 implicit conversions 部分

    价值丢弃。 如果 e 具有某个值类型并且预期类型是 Unit,则通过将 e 嵌入到术语 {e; 中,将 e 转换为预期类型。 () }。

    【讨论】:

      【解决方案3】:

      除了Ben Reich的回答:

      从概念上讲,在 Scala 中,Unit 类型是所有其他类型的超类型。因此,每个值,包括Int,都可以分配给Unit。实际上,如果用作方法的返回类型,编译器将丢弃结果值,为方法提供 JVM/Java void 类型。

      Nothing 正好相反,顺便说一句:从概念上讲,它是所有其他类型的子类型。由于不存在Nothing 的实例,因此任何其他类型的实例都不能与Nothing 赋值兼容。

      Java 的 void 不知何故是这两者的不完全混合。

      【讨论】:

      • 你把UnitAny混在一起了吗?
      • @acjay 不,这就是 Unit and Nothing 的概念。它不是由 Scala 发明的。许多强类型函数式语言具有相同的概念。有时名称可能不同,例如,Nothing 可能被称为底部。
      • 我没有投反对票,但现在我投票支持你再次为你带来:)
      • 哦,谢谢。 :-) 我不认为你投了反对票。
      • 这是不正确的。 Unit 不是所有其他类型的超类型。 UnitAnyVal 的子类型,这是一组非常有限的类型。请参阅scaladocs for Unit。并不是您将Int 分配给Unit,而是编译器通过插入; () 完全丢弃了Int 值。在其他语言中可能会有所不同,但在 Scala 中并非如此。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-09
      • 2011-03-31
      • 1970-01-01
      • 2015-04-18
      • 2011-03-19
      • 2017-06-22
      • 2022-12-19
      相关资源
      最近更新 更多