为什么在scala中传递一些函数需要_

时间:2017-06-24 11:00:00

标签: scala functional-programming

更好地了解scala,我遇到了一个我无法解释的行为。 以下代码工作正常:

def triple(x: Double) = 3 * x
Array(3.14,1.42,3.9).map(triple)

但是,如果我在数学库中调用scala ceil函数,那么我需要传递_才能使其工作

def valueAtOneQuarter(f: (Double)=> Double) = f(0.25)
valueAtOneQuarter(sqrt _)

在此上下文中,来自前一段代码中的函数调用的_有什么特别之处。

3 个答案:

答案 0 :(得分:3)

下划线实际上已扩展为一个函数。

所以sqrt _变成了函数a => sqrt(a)

您会注意到此扩展函数与valueatonequarter方法的参数类型f匹配。

更一般地说,下划线有时需要标记给编译器以将方法(使用def声明的方法)转换为函数(方法和函数类似但不相同)。编译器将尝试自动将方法转换为函数,但在某些情况下,它需要额外的指针(如显式类型声明或_)。有关eta扩展和部分函数的完整说明,请参见此处:https://medium.com/@sinisalouc/on-method-invocations-or-what-exactly-is-eta-expansion-1019b37e010c

答案 1 :(得分:1)

Scala中的方法和函数不同。

您可以通过这种方式定义方法:

def method(x:Double):Double = ...

但是你用这种方式定义一个函数:

val func = (x: Double):Double => {...}

将函数作为参数传递给方法时,它必须是函数,而不是方法。

所以你必须使用下划线从方法中创建一个函数。

有时Scala使用“Eta Expansion”功能自动将方法转换为函数。但在某些情况下,您必须手动执行此操作

答案 2 :(得分:1)

回答,因为现有的答案并不能解释何时需要_,只是"有时"或者"在某些情况下"。

要在Scala中理解的一个非常重要的概念是期望类型。在您的第一个示例中,map参数的预期类型为Double => B,其中包含一些未知B;在第二个Double => Double中。当期望的类型是函数类型并且传递方法名称时,它将自动转换为函数。因此,正如评论所说,第二个例子没有_。只有在没有预期类型的​​情况下才需要它,比如说

val f = sqrt _

当方法过载时也可能存在问题,但只是添加_通常也不会起作用;相反,您将指定参数类型以显示使用哪种方法,例如max(_: Int, _: Int)max(_: Double, _: Double)

  

谢谢似乎_在scala的不同上下文中有不同的含义

是的,不少:What are all the uses of an underscore in Scala?

相关问题