通过插入()修改参数列表已被弃用

时间:2014-08-17 17:54:19

标签: scala

我正处于从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在认为需要导致其他问题

3 个答案:

答案 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上重现这一点。