何时明确说明函数的输入类型?
When to explicitly state types of inputs of functions?
我能够计算出 spark 集合中每个起始字母的平均字长
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))
我不明白的是:为什么我需要在第二个示例中明确说明函数中的类型,而第一个示例的函数可以不用?
我说的是
(x, y) => (x._1 + y.length, x._2 + 1),
(x, y) => (x._1 + y._1, x._2 + y._2)
对
(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)
它可能更像是一个 Scala 问题而不是 Spark 问题。
Why am I required to explicitly state the types in the functions in
the second example while the first example's functions can do without?
因为在第一个示例中,编译器能够根据提供的第一个参数列表推断出 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)]
并且在没有明确说明类型的情况下,编译器不知道要将 x
和 y
推断为什么。
你可以做些什么来帮助编译器显式指定类型参数:
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
我能够计算出 spark 集合中每个起始字母的平均字长
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))
我不明白的是:为什么我需要在第二个示例中明确说明函数中的类型,而第一个示例的函数可以不用?
我说的是
(x, y) => (x._1 + y.length, x._2 + 1),
(x, y) => (x._1 + y._1, x._2 + y._2)
对
(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)
它可能更像是一个 Scala 问题而不是 Spark 问题。
Why am I required to explicitly state the types in the functions in the second example while the first example's functions can do without?
因为在第一个示例中,编译器能够根据提供的第一个参数列表推断出 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)]
并且在没有明确说明类型的情况下,编译器不知道要将 x
和 y
推断为什么。
你可以做些什么来帮助编译器显式指定类型参数:
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