【发布时间】:2017-08-09 22:15:35
【问题描述】:
如果我有一个简单的 Scala 整数集合,并且我定义了一个简单的 方法 isPositive 以在值大于 0 时返回 true,那么我可以将方法传递给 @987654322集合的@方法,如下例所示
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)
据我了解,编译器能够通过eta扩展自动将方法转换为函数实例,然后将这个函数作为参数传递。
但是,如果我对 Spark 数据集做同样的事情:
val aDataset = aList.toDS
val newDataset = aDataset.filter(isPositive)
> error
它因众所周知的“方法缺少参数”错误而失败。为了使它工作,我必须使用“_”将方法显式转换为函数:
val newDataset = aDataset.filter(isPositive _)
> newDataset: org.apache.spark.sql.Dataset[Int] = [value: int]
尽管使用map 它可以按预期工作:
val newDataset = aDataset.map(isPositive)
> newDataset: org.apache.spark.sql.Dataset[Boolean] = [value: boolean]
调查签名,我发现Dataset的过滤器的签名与List的过滤器非常相似:
// Dataset:
def filter(func: T => Boolean): Dataset[T]
// List (Defined in TraversableLike):
def filter(p: A => Boolean): Repr
那么,为什么编译器不对 Dataset 的过滤操作进行 eta 扩展呢?
【问题讨论】:
-
可能是因为 Scala TraversableLike 中的
filter没有重载,并且在 Spark 数据集中有很多选项 -
@T.Gawęda 同样代表
map,但它对数据集的工作方式与预期相同。这就是我添加地图示例的原因。 -
你是对的!所以等待真正的答案:)
-
等等,但地图确实有一个额外的隐式参数,编码器
-
@T.Gawęda 我明白了...... map 的“Java”版本将编码器作为第二个参数,因此编译器只为单参数
map找到一个选项,因此它是能够进行转换。但是,对于过滤器,它会找到具有单个参数的多个候选者。我会做一些测试来验证是否是这个原因。
标签: scala apache-spark