以下代码http://www.scalaclass.com/book/export/html/1做矩阵点积。
我无法理解大括号之间的语法。
感谢。
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(_ + _)
答案 0 :(得分:36)
当参数是匿名函数时,有些人更喜欢使用花括号。首先,花括号启用模式匹配匿名函数,而括号不支持。在这个特定的例子中,不需要大括号。
以下是需要花括号的示例(由于case
模式匹配):
def dotProd(v1:Row, v2:Row) =
v1.zip(v2).map{ case (a, b) => a * b }.reduceLeft(_ + _)
请注意,上述功能与问题中的功能完全相同,只是略有不同。
t
是匿名方法吗?不,这是一个参数。就像v1
和v2
是dotProd
的参数一样,t
是传递给map
的匿名函数的参数。
._1
和._2
? t
上的方法。参数t
被定义为元组(具体地,Tuple2[Double, Double]
,可以写为(Double, Double)
),元组允许您使用以下方法提取元组的每个成员:{ {1}},_1
,_2
等
_3
当然只有Tuple2
和_1
。请注意,由于其他函数语言的影响,第一个参数是_2
,而不是_1
。
无论如何,_0
方法会将zip
(Row
)转换为List[Double]
。方法List[(Double, Double)]
采用一个函数将列表的元素(map
元组)转换为其他元素。
答案 1 :(得分:19)
在这种特殊情况下,花括号与普通旧语法相比没有优势,但一般来说,使用花括号的好处是它们允许您在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元素的访问。
答案 2 :(得分:5)
在这个问题中,你可以找到一个非常好的答案来解决大括号{}和括号()之间的差异:What is the formal difference in Scala between braces and parentheses, and when should they be used?
对于_1,_2,请参阅Meaning of _2 sign in scala language。
是的,t:(Double, Double) => t._1 * t._2
是一个匿名函数(实际上不是一个方法)。 Difference between method and function in Scala
答案 3 :(得分:1)
花括号表示一个类型为Tuple2[Double,Double] => Double
的匿名函数。该参数被赋予本地名称t
,因此t
是两个双元组的元组。t._1
表示第一个项目,t._2
表示第二个项目。
因此map
会生成两个向量组件的元素乘积列表,reduceLeft
对这些乘积进行求和以计算点积。