这是一个例子:
$ scala
Welcome to Scala 2.11.8 (OpenJDK 64-Bit Server VM, Java 1.8.0_112).
Type in expressions for evaluation. Or try :help.
scala> val a: Unit = 1
<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
val a: Unit = 1
^
a: Unit = ()
Run Code Online (Sandbox Code Playgroud)
在Scala文档中:
There is only one value of type Unit, ()
Run Code Online (Sandbox Code Playgroud)
为什么Scala编译器默默地将值强制转换为Unit?
一点上下文:我使用Future[Unit]类型来描述一些不返回任何内容的过程.由于Future[Unit]现在实际上是一个子类型Unit,我得到了一些有趣的错误(someFuture.map(a => Future(a))默默地跳过调用操作而不是给出编译警告).我应该使用什么作为一种不会返回任何有意义结果的操作?
Unit不是其他类型的超类型.相反,它被称为值丢弃:当表达式的预期类型e是Unit,编译器将其替换为{e; ()}.这样做是为了使某些行为更加熟悉.例如
val sb = new StringBuilder
val strings: List[String] = ...
for (str <- strings) { sb.append(str) }
Run Code Online (Sandbox Code Playgroud)
通过与for其他语言中的循环类比,我们希望它能够编译.但是,如果没有价值丢弃它不会:这相当于strings.foreach(str => sb.append(str)),类型str => sb.append(str)是String => StringBuilder(因为所有append的方法StringBuilder返回的建设者本身),并foreach在List[String]需要String => Unit.
您可以添加-Ywarn-value-discard编译器选项以在发生时警告您(并for (sb <- sbOpt) { sb.append("a"); () }显式写入).
或者您实际上可以使用定义自己的技巧Unit(可能更改名称以避免混淆任何人阅读您的代码):
object Unit
type Unit = Unit.type
implicit def unit2scalaunit(a: Unit): scala.Unit = ()
implicit def scalaunit2unit(a: scala.Unit): Unit = Unit
Run Code Online (Sandbox Code Playgroud)
这应该避免与Future您描述的问题.