通过插入 () 来调整参数列表已被弃用

问题描述 投票:0回答:3

我正在从 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
会导致 其他问题

scala
3个回答
80
投票

自动

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 — 过去、现在和未来


4
投票

也许应该是

Right(())
。你尝试过吗?


4
投票

我的解释是,由于

Right.apply
是多态的,它可以接受所有类型的参数,执行
Right()
意味着传入
Unit
,编译器只是告诉你也许这不是你想要的,他不知道这就是你真正想要的。

如果您看到弃用消息,则显示:

...适应后:Right((): Unit)

这意味着编译器自动决定您传递的是

Unit
,因为这有点像
void
他并不真正喜欢它,特别是传递像
Unit
这样的
()
明确告诉编译器你确实想要一个
Unit
。不管怎样,似乎是 scala 2.11 的新弃用,我无法在 2.10.4 上重现它。

© www.soinside.com 2019 - 2024. All rights reserved.