我正在从 Scala 2.10.x 升级到 2.11.2,并且收到以下警告,代码如下:
override def validateKey(key: String): Either[InvalidKeyError, Unit] =
keys.contains(key) match {
case true => Right()
case false => Left(InvalidKeyError(context, key))
}
Adaptation of argument list by inserting () has been deprecated: this is unlikely to be what you want. signature: Right.apply[A, B](b: B): scala.util.Right[A,B] given arguments: <none> after adaptation: Right((): Unit)
我可以通过将
true
case 语句更改为: 来解决此问题
case true => Right(()) //() is a shortcut to a Unit instance
这是解决此警告的正确方法吗?
也许“为什么我们现在必须这样做”类型的答案是合适的。 我的粗略调查似乎表明 Scala 在认为需要时插入
Unit
会导致 其他问题。
自动
Unit
推理在scala 2.11中已被弃用,其背后的原因是它可能导致令人困惑的行为,特别是对于学习该语言的人来说。
这是一个例子
class Foo[T](value: T)
val x = new Foo
这不应该编译,对吧?您正在调用不带参数的构造函数,而此时需要参数。令人惊讶的是,直到 scala 2.10.4 为止,它都可以正常编译,没有错误或警告。
那是因为编译器推断出一个
Unit
参数,所以它实际上用 替换了你的代码
val x = new Foo[Unit](()) // Foo[Unit]
正如新引入的警告消息所说,这不太可能是您想要的。
另一个著名的例子是这个
scala> List(1,2,3).toSet()
// res1: Boolean = false
调用
toSet()
应该是一个编译时错误,因为 toSet
不带参数,但编译器拼命试图让它编译,最终将代码解释为
scala> List(1,2,3).toSet.apply(())
这意味着:测试
()
是否属于集合。由于事实并非如此,您会得到 false
!
因此,从 scala 2.11 开始,如果要传递
()
(又名 Unit
)作为参数,则必须明确。这就是为什么你必须写:
Right(())
而不是
Right()
示例取自 Simon Ochsenreither 的简化 Scala — 过去、现在和未来。
也许应该是
Right(())
。你尝试过吗?
我的解释是,由于
Right.apply
是多态的,它可以接受所有类型的参数,执行 Right()
意味着传入 Unit
,编译器只是告诉你也许这不是你想要的,他不知道这就是你真正想要的。
如果您看到弃用消息,则显示:
...适应后:Right((): Unit)
这意味着编译器自动决定您传递的是
Unit
,因为这有点像 void
他并不真正喜欢它,特别是传递像 Unit
这样的 ()
明确告诉编译器你确实想要一个 Unit
。不管怎样,似乎是 scala 2.11 的新弃用,我无法在 2.10.4 上重现它。