Spark的RDD中的两个groupBy
方法声明为:
def groupBy[K](f: T => K)(implicit kt: ClassTag[K]): RDD[(K, Iterable[T])]
def groupBy[K](f: T => K, numPartitions: Int)(implicit kt: ClassTag[K]): RDD[(K, Iterable[T])]
我将函数f定义为:
def f(x: Int): Int = x % 2
我可以将f作为groupBy
传递给第一个rdd.groupBy(f)
。为什么我不能将f作为groupBy
传递到第二个rdd.groupBy(f, 10)
?我必须使用rdd.groupBy(f(_), 10)
或rdd.groupBy(x => f(x), 10)
。
答案 0 :(得分:3)
我将函数f定义为:
def f(x: Int): Int = x % 2
这不是一个函数,那是一个方法。这两个从根本上不同:
这些是函数与方法相比的4个限制。现在,如果它们如此受限制,我们为什么要使用它们呢?嗯,功能有一个主要优点:
这意味着:函数可以分配给val
s / var
,它们可以作为参数传递给函数,方法和构造函数,它们可以从函数和方法返回。方法无法做到这一点:Scala是一种面向对象的语言,程序可以操作的所有实体都是对象......而方法则不是。
那么,为什么
rdd.groupBy(f)
工作?
好吧,您可以通过η-expansion将方法转换为部分应用的函数(此处“部分应用”表示“部分应用于this
”,而不是参数的子集)
val fn = f _
// => fn: Int => Int = <function1>
这里,与Scala中的情况一样,下划线用作占位符(在这种情况下,用于尚未提供的参数)。我们修复了方法的this
并将参数保持打开状态,并创建了与该方法对应的函数。
在一些的情况下,Scala会知道你想要执行η-expansion甚至而不用明确提供下划线。这就是为什么
rdd.groupBy(f)
的工作原理。这称为隐式η-扩展(Scala语言规范的第6.26.2节案例3),由于含糊不清,仅适用于有限数量的情况。
然而,在解释了所有这些之后,我必须承认,我不明白为什么你的第二个例子不起作用。根据我对规范的解读,它应该。
IOW:您似乎遇到的基本问题是您混淆了函数和方法,但在这个特殊情况中,它应该实际工作(至少根据我对规范的解释,虽然显然不是根据编译器编写者的解释而来的。)