我注意到当我使用期望其他函数作为参数的函数时,我有时可以这样做:
someFunction(firstParam,anotherFunction)
Run Code Online (Sandbox Code Playgroud)
但其他时候,编译器给我一个错误,告诉我应该编写一个这样的函数,以便将它视为部分应用的函数:
someFunction(firstParam,anotherFunction _)
Run Code Online (Sandbox Code Playgroud)
例如,如果我有这个:
object Whatever {
def meth1(params:Array[Int]) = ...
def meth2(params:Array[Int]) = ...
}
import Whatever._
val callbacks = Array(meth1 _,meth2 _)
Run Code Online (Sandbox Code Playgroud)
为什么我不能拥有如下代码:
val callbacks = Array(meth1,meth2)
Run Code Online (Sandbox Code Playgroud)
在什么情况下编译器会告诉我添加_?
我可能会丢失一些东西,但是遇到了一种意外地无法工作的模式。
这里是:
object A {
def bar(func: (Int, Int) => Int): Int = 2
def bar(func: Int => Int): Int = 3
def foo(func: Int => Int): Int = 4
}
def f(n: Int) : Int = n + 1
val g: Int => Int = f
A.foo(f) // works fine
A.bar(f) // doesn't work
A.bar(g) // but this works
Run Code Online (Sandbox Code Playgroud)
编译器要求我显式应用该方法f以将其传递(编写f _):
Unapplied methods are only converted to functions when a function type is expected.
我不明白为什么在传递 …
我有一个简单的类和一个伴随对象的应用方法重载:
case class A(val s: String,
val x: Int,
val y: Int,
val z: Int,
val foo: Int => Int,
val l: Option[List[String]])
object A {
def apply(s: String, x: Int, y: Int, z: Int, foo: Int => Int) =
new A(s, x, y, z, foo, None)
def apply(s: String, x: Int, y: Int, z: Int, foo: Int => Int, l: List[String]) =
new A(s, x, y, z, foo, Some(l))
}
Run Code Online (Sandbox Code Playgroud)
我们还定义一个函数:
def foo(x: Int): Int = x + 1 …Run Code Online (Sandbox Code Playgroud) 如果我有一个简单的Int Scala集合,并且我定义了一个简单的方法 isPositive,如果值大于0则返回true,那么我可以将方法传递给filter集合的方法,如下例所示
def isPositive(i: Int): Boolean = i > 0
val aList = List(-3, -2, -1, 1, 2, 3)
val newList = aList.filter(isPositive)
> newList: List[Int] = List(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)
因此,据我所知,编译器能够通过执行eta扩展自动将方法转换为函数实例,然后将此函数作为参数传递.
但是,如果我使用Spark数据集做同样的事情:
val aDataset = aList.toDS
val newDataset = aDataset.filter(isPositive)
> error
Run Code Online (Sandbox Code Playgroud)
它失败了众所周知的"缺少方法参数"错误.为了使它工作,我必须使用"_"显式地将方法转换为函数:
val newDataset = aDataset.filter(isPositive _)
> newDataset: org.apache.spark.sql.Dataset[Int] = [value: int]
Run Code Online (Sandbox Code Playgroud)
虽然map它按预期工作:
val newDataset = aDataset.map(isPositive)
> newDataset: org.apache.spark.sql.Dataset[Boolean] = [value: boolean]
Run Code Online (Sandbox Code Playgroud)
调查签名,我看到Dataset过滤器的签名与List的过滤器非常相似:
// Dataset:
def filter(func: T => Boolean): …Run Code Online (Sandbox Code Playgroud)