何时明确说明函数的输入类型?

时间:2016-05-18 10:47:56

标签: scala apache-spark language-concepts

我能够计算火花集合每个起始字母的平均字长

QString l_str "STARTfoo barENDSTARThi there!ENDSTARTstackoverflowrulezEND"; 
QRegExp rx("(START)(\w+)(END)");
QStringList list;
int pos = 0;
while ((pos = rx.indexIn(l_str, pos)) != -1)
{
    list << rx.cap(1);
    pos += rx.matchedLength();
}
qWarning() << list;

或者

val animals23 = sc.parallelize(List(("a","ant"), ("c","crocodile"), ("c","cheetah"), ("c","cat"), ("d","dolphin"), ("d","dog"), ("g","gnu"), ("l","leopard"), ("l","lion"), ("s","spider"), ("t","tiger"), ("w","whale")), 2)

animals23.
    aggregateByKey((0,0))(
        (x, y) => (x._1 + y.length, x._2 + 1),
        (x, y) => (x._1 + y._1, x._2 + y._2)
    ).
    map(x => (x._1, x._2._1.toDouble / x._2._2.toDouble)).
    collect

每个导致

animals23.
    combineByKey(
        (x:String) => (x.length,1),
        (x:(Int, Int), y:String) => (x._1 + y.length, x._2 + 1),
        (x:(Int, Int), y:(Int, Int)) => (x._1 + y._1, x._2 + y._2)
    ).
    map(x => (x._1, x._2._1.toDouble / x._2._2.toDouble)).
    collect

我不明白:为什么我需要在第二个例子中明确说明函数中的类型,而第一个例子的函数却没有?

我在谈论

Array((a,3.0), (c,6.333333333333333), (d,5.0), (g,3.0), (l,5.5), (w,5.0), (s,6.0), (t,5.0))

VS

(x, y) => (x._1 + y.length, x._2 + 1),
(x, y) => (x._1 + y._1, x._2 + y._2)

它可能更像是Scala而不是Spark问题。

1 个答案:

答案 0 :(得分:2)

  

为什么我需要在函数中明确说明类型   第二个例子,而第一个例子的功能可以没有?

因为在第一个示例中,编译器能够根据提供的第一个参数列表推断seqOp的类型。 aggregateByKey正在使用currying

def aggregateByKey[U](zeroValue: U)
                     (seqOp: (U, V) ⇒ U, 
                      combOp: (U, U) ⇒ U)
                     (implicit arg0: ClassTag[U]): RDD[(K, U)]

type inference在Scala中的工作方式是,编译器能够根据第一个参数列表推断出第二个参数列表的类型。因此,在第一个示例中,它知道seqOp是一个函数((Int, Int), String) => (Int, Int),同样适用于combOp

相反,combineByKey只有一个参数列表:

combineByKey[C](createCombiner: (V) ⇒ C, 
                mergeValue: (C, V) ⇒ C, 
                mergeCombiners: (C, C) ⇒ C): RDD[(K, C)] 

如果没有明确说明类型,编译器就不知道要将xy推断为什么。

如何帮助编译器明确指定类型参数:

animals23
  .combineByKey[(Int, Int)](x => (x.length,1), 
                           (x, y) => (x._1 + y.length, x._2 + 1),
                           (x, y) => (x._1 + y._1, x._2 + y._2))
  .map(x => (x._1, x._2._1.toDouble / x._2._2.toDouble))
  .collect