27

下面的代码来自http://www.scalaclass.com/book/export/html/1做矩阵点积。

我无法理解大括号之间的语法。

  • 为什么使用大括号,而不是常规方法括号?
  • 不是匿名方法吗?
  • ._1 和 ._2 是什么?

谢谢。

type Row    = List[Double]
type Matrix = List[Row]

def dotProd(v1:Row, v2:Row) = 
    v1.zip(v2).map{ t:(Double, Double) => t._1 * t._2 }.reduceLeft(_ + _)
4

4 回答 4

39
  • 为什么使用大括号,而不是常规方法括号?

当参数是匿名函数时,有些人更喜欢使用花括号。一方面,花括号启用了模式匹配匿名函数,而括号则没有。在这个特定的示例中,不需要花括号。

这是一个需要花括号的示例(因为case模式匹配):

def dotProd(v1:Row, v2:Row) = 
    v1.zip(v2).map{ case (a, b) => a * b }.reduceLeft(_ + _)

请注意,上述函数与问题中的函数完成相同的事情,但方式略有不同。

  • t匿名方法吗?

不,它是一个参数。就像v1v2的参数一样dotProdt是传递给 的匿名函数的参数map

  • 什么是._1._2

上的方法t。该参数t被定义为一个元组(具体来说,Tuple2[Double, Double],可以写成(Double, Double)),并且元组允许您使用以下方法提取元组的每个成员:_1_2_3等。

A当然Tuple2只有_1_2。请注意,第一个参数是_1,而不是_0,因为受到其他函数式语言的影响。

无论如何,该zip方法会将Row( List[Double]) 转换为List[(Double, Double)]. 该方法采用将列表元素(元组)转换为其他map元素的函数。(Double, Double)

于 2012-05-03T17:42:28.690 回答
22

在这种特殊情况下,大括号与普通的旧语法相比没有优势,但总的来说,使用大括号的好处是它们允许您在其中编写模式匹配表达式map ...

所以我可以重写这个

.map{ t:(Double, Double) => t._1 * t._2 }

进入这个

.map{ case(a: Double, b: Double) => a*b }

但这不会编译:

.map( case(a: Double, b: Double) => a*b )

正如 Lee 所说,._1, ._2 提供对 N 元组的第一个、第二个、... N 元素的访问。

于 2012-05-03T12:44:49.200 回答
5

您可以在这个问题中找到关于大括号 {} 和圆括号 () 之间区别的一个很好的答案:Scala 中大括号和圆括号之间的形式区别是什么,什么时候应该使用它们?

对于 _1, _2,请参阅_2 sign in scala language 的含义

是的,t:(Double, Double) => t._1 * t._2是一个匿名函数(实际上不是方法)。Scala中方法和函数的区别

于 2012-05-03T12:45:27.237 回答
1

大括号表示具有类型的匿名函数Tuple2[Double,Double] => Double。该参数被赋予本地名称t,因此t是两个双精度的元组。t._1指第一项和t._2第二项。

因此map产生两个向量分量的元素乘积列表,并将reduceLeft这些乘积求和以计算点积。

于 2012-05-03T12:03:29.863 回答