在 Scala 中,为什么我可以在此处使用 `Unit` 作为 return 类型?
In Scala, why can I use `Unit` as return type here?
代码如下:
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
的 return 类型是 Unit
,它是 AnyVal
的子类型而不是 Int
的超类型,因此,我无法理解为什么 1
可以用作 returned 值。
在第二个表达式中,_=>2
还使用 2
而不是 Unit
作为 returned 值,这与定义冲突。
在第三个表达式中,_=> List(1,2)
甚至使用 List
,AnyRef
的子类型作为 returned 值,但是 REPL 仍然没有抱怨这个..
有没有人知道为什么 Unit
可以容忍这里的非子类型类型转换?谢谢!
Scala 会在这种情况下自动插入 ()
(单例 Unit
值)以进行类型检查。所以你所拥有的相当于:
def f(x:Int => Unit):Unit = { 1; () }
这在 Scala 中称为 "value discarding"。来自 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; () }
就像在许多编程语言中一样,这只是为了方便 "throwing out" 表达式的 return 值。这允许您创建一个 Unit
类型的方法,它只使用表达式的副作用。
检查 SLS 中的 implicit conversions 部分
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; () }.
另外Ben Reich的回答:
从概念上讲,在 Scala 中,类型 Unit
是所有其他类型的超类型。因此,每个值,包括 Int
,都可以分配给 Unit
。实际上,如果用作方法的 return 类型,编译器将丢弃结果值,将方法赋予 JVM/Java void
类型。
Nothing
恰恰相反,顺便说一句:从概念上讲,它是所有其他类型的子类型。由于不存在 Nothing
的实例,因此任何其他类型的实例都不能与 Nothing
.
赋值兼容
Java 的 void
不知何故是两者的不完整混合。
代码如下:
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
的 return 类型是 Unit
,它是 AnyVal
的子类型而不是 Int
的超类型,因此,我无法理解为什么 1
可以用作 returned 值。
在第二个表达式中,_=>2
还使用 2
而不是 Unit
作为 returned 值,这与定义冲突。
在第三个表达式中,_=> List(1,2)
甚至使用 List
,AnyRef
的子类型作为 returned 值,但是 REPL 仍然没有抱怨这个..
有没有人知道为什么 Unit
可以容忍这里的非子类型类型转换?谢谢!
Scala 会在这种情况下自动插入 ()
(单例 Unit
值)以进行类型检查。所以你所拥有的相当于:
def f(x:Int => Unit):Unit = { 1; () }
这在 Scala 中称为 "value discarding"。来自 spec:
Value Discarding
If
e
has some value type and the expected type isUnit
,e
is converted to the expected type by embedding it in the term{ e; () }
就像在许多编程语言中一样,这只是为了方便 "throwing out" 表达式的 return 值。这允许您创建一个 Unit
类型的方法,它只使用表达式的副作用。
检查 SLS 中的 implicit conversions 部分
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; () }.
另外Ben Reich的回答:
从概念上讲,在 Scala 中,类型 Unit
是所有其他类型的超类型。因此,每个值,包括 Int
,都可以分配给 Unit
。实际上,如果用作方法的 return 类型,编译器将丢弃结果值,将方法赋予 JVM/Java void
类型。
Nothing
恰恰相反,顺便说一句:从概念上讲,它是所有其他类型的子类型。由于不存在 Nothing
的实例,因此任何其他类型的实例都不能与 Nothing
.
Java 的 void
不知何故是两者的不完整混合。