为什么_(下划线)类型单位和()处理方式不同?

时间:2017-12-04 10:47:21

标签: scala

我有一个返回Future[Unit]的方法,所以当我拨打whenReady

这两个选项有效:whenReady(doItAsync())(_ => {})whenReady(doItAsync()) { _ => }

但这并不是:whenReady(doItAsync())(() => {})

在这种情况下,_类型Unit和空参数列表是否等同?

2 个答案:

答案 0 :(得分:2)

虽然类型Unit类似于其他语言的void,但它并不完全相同。 这个特殊问题来自Java(以及Scala)泛型实现的限制:它们是使用type erasure实现的。特别是它意味着泛型方法不能改变参数的数量。现在当类型参数为Unit时会发生什么?我们仍然必须具有相同数量的参数,并且也不能神奇地改变返回类型以返回任何内容(void),因为这将是一个不同的签名。所以答案是使用一些只有伪造值的假类型:scala.runtime.BoxedUnit。因此Unit可能代表您不需要但必须存在的实际参数。因此类型签名() => {}与此不匹配,因为它不带参数。

另请注意,在Java本身存在同样的问题,因此有类似的事情称为java.lang.Void

<强>更新

为了更清楚地说明如何遵循通用代码与非通用代码:

def foo(f: () => String) = println(f())

def fooGeneric[T](arg: T, f: (T) => String) = println(f(arg))

foo(() => "Non-generic")
fooGeneric[Unit]((), (_) => "generic")

请注意,逻辑上fooGeneric[Unit]foo相同,您仍然必须传递第一个参数并传递接受(无用)参数的函数作为第二个参数。

答案 1 :(得分:2)

  

在这种情况下,不是_类型单位和空参数列表等同吗?

没有。 _ => {}使用单个参数定义一个函数(在此上下文中发生类型Unit),() => {}定义一个没有参数的函数。他们的类型是Unit => Unit() => Unit,或没有句法糖Function1[Unit, Unit]Function0[Unit]。这些类型实际上并不相关:它们都不是另一个的子类型。

您可以使用模式匹配Unit编写使用() { case () => ... }的单参数匿名函数。pentaho-server-ce-7.1.0.0-12。但没有必要这样做。