gpt4 book ai didi

scala - 数据集过滤器: eta expansion is not done automatically

转载 作者:行者123 更新时间:2023-12-02 04:25:46 25 4
gpt4 key购买 nike

如果我有一个简单的 Scala Int 集合,并且定义了一个简单的方法 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)

据我了解,编译器能够通过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:
def filter(func: T => Boolean): Dataset[T]

// List (Defined in TraversableLike):
def filter(p: A => Boolean): Repr

那么,为什么编译器不为数据集的过滤操作进行 eta 扩展?

最佳答案

这是由于重载方法和 ETA 扩展的本质造成的。 Eta-expansion between methods and functions with overloaded methods in Scala解释了为什么失败。

其要点如下(强调我的):

when overloaded, applicability is undermined because there is no expected type (6.26.3, infamously). When not overloaded, 6.26.2 applies (eta expansion) because the type of the parameter determines the expected type. When overloaded, the arg is specifically typed with no expected type, hence 6.26.2 doesn't apply; therefore neither overloaded variant of d is deemed to be applicable.

......

Candidates for overloading resolution are pre-screened by "shape". The shape test encapsulates the intuition that eta-expansion is never used because args are typed without an expected type. This example shows that eta-expansion is not used even when it is "the only way for the expression to type check."

正如 @DanielDePaula 指出的,我们在 DataSet.map 中看不到这种效果的原因是重载方法实际上需要一个额外的 Encoder[U] 参数:

def map[U : Encoder](func: T => U): Dataset[U] = withTypedPlan {
MapElements[T, U](func, logicalPlan)
}

def map[U](func: MapFunction[T, U], encoder: Encoder[U]): Dataset[U] = {
implicit val uEnc = encoder
withTypedPlan(MapElements[T, U](func, logicalPlan))
}

关于scala - 数据集过滤器: eta expansion is not done automatically,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45591980/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com