加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 数据集过滤器:eta扩展不会自动完成

发布时间:2020-12-16 18:14:38 所属栏目:安全 来源:网络整理
导读:如果我有一个简单的Int Scala集合,我定义了一个简单的方法isPositive,如果该值大于0则返回true,那么我可以将该方法传递给集合的filter方法,如下例所示 def isPositive(i: Int): Boolean = i 0val aList = List(-3,-2,-1,1,2,3)val newList = aList.filter(is
如果我有一个简单的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,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]

虽然使用地图它按预期工作:

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

那么,为什么编译器不为数据集的过滤操作进行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,logicalPlan))
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读