我正处于从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))
}
插入()的参数列表的改编已被弃用:这个 不太可能是你想要的。签名:Right.apply [A,B](b:B): scala.util.Right [A,B]给出参数:改编后: 对(():单位)
我可以通过将“true”case语句更改为:
来解决这个问题case true => Right(()) //() is a shortcut to a Unit instance
这是解决此警告的正确方法吗?
编辑:也许是“为什么我们现在必须这样做”类型的答案是合适的,我的粗略调查似乎表明Scala在认为需要导致其他问题
答案 0 :(得分:65)
自动Unit
推理has been deprecated in 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从Simplifying Scala — The Past, Present and Future获取的示例。
答案 1 :(得分:3)
也许它应该是Right(())
。你试过了吗?
答案 2 :(得分:3)
我的解释是,由于Right.apply
是多态的,它可以采用所有类型的参数,执行Right()
意味着传入Unit
并且编译器只是告诉你可能那不是什么你想要,他不知道这是你真正想要的。
如果您看到弃用消息,则说明:
......适应后:右(():单位)
这意味着编译器已自动决定您传入Unit
,因为这有点像void
他并不喜欢它,特别是传入Unit
像()
明确告诉编译器你确实需要Unit
。无论如何似乎是一个新的弃用形式scala 2.11,我无法在2.10.4上重现这一点。