object Test1 {
def main(args: Array[String]) {
val list = List("a", "b")
list map { x ⇒ println(x) }
list map { case x ⇒ println(x) }
val list2 = List(("aa", "11"))
list2 map {
case (key, value) ⇒ println("key: "+key+", value: "+value)
}
}
}
请注意最后一行,为什么必须使用关键字case
,但list map { x ⇒ println(x) }
可以将其删除?
答案 0 :(得分:14)
你无法打破函数文字中的元组。这就是为什么你必须用case来匹配它们。另一种方法是使用 tupled 来使你的函数有两个适合的参数:
import Function.tupled
list2 map tupled {
(key, value) => println("key: "+key+", value: "+value)
}
答案 1 :(得分:9)
{ case (key, value) => f }
与
不同{ (key, value) => f }
第一种是模式匹配,将Tuple2
分解为其组件,将其值分配给key
和value
。在这种情况下,只传递一个参数(元组)。 { x => println(x) }
有效,因为为x
分配了元组,println
会将其打印出来。
第二个是一个函数,它接受两个参数,并且不进行模式匹配。由于map
需要一个采用单个参数的函数,因此第二种情况与map
不兼容。
答案 2 :(得分:4)
list2
包含Tuple2[Int, Int]
类型的元素,因此您必须传递的函数的签名(在这种情况下...... foreach
是一个更自然的选择t return something)是Tuple2[Int, Int] => Unit
。也就是说,它只需要Tuple2[Int, Int]
类型的单个参数。
由于Tuple2支持unapply
,你可以使用模式匹配来分解函数中的元组,如下所示:
{
case (key, value) ⇒ println("key: "+key+", value: "+value)
}
此功能的签名仍为Tuple2[Int, Int] => Unit
它与相同的字节码相同,并且可能编译为:
{
x: Tuple2[Int, Int] => println("key: "+x._1+", value: "+x._2)
}
这是Scala以非常愉快的方式结合正交概念的众多例子之一。
答案 3 :(得分:3)
list2 map { x => println(x) }
对我没有任何问题。如果你想进行模式匹配(根据结构将你的参数分成它的部分),你需要始终case
。或者你可以写:
list2 map { x => println("key: "+x._1+", value: "+x._2) }
BTW,map
应该用于转换另一个列表。如果您只想浏览列表的所有元素,请使用foreach
或进行理解。
答案 4 :(得分:1)
我仍在学习Scala,但我相信正在发生的事情是你已经定义了一个带有一个参数的部分函数。当调用List.map或List.foreach等只需要一个参数的方法时,可以省略下划线或命名val。
在闭包中省略val名称的示例:
val v = List("HEY!", "BYE!")
v.foreach { Console.println } // Pass partial function, automatically
这与:
相同val v = List("HEY!", "BYE!")
v.foreach { Console.println _ } // Pass partial function, explicitly
使用匿名val:
val v = List("HEY!", "BYE!")
v.foreach { Console.println(_) } // Refer to anonymous param, explicitly
或使用命名val:
val v = List("HEY!", "BYE!")
v.foreach { x => Console.println(x) } // Refer to val, explicitly
在你的闭包中你使用一个部分函数(case语句),它接受一个匿名变量并立即将它变成一个绑定到两个独立变量的元组。
我想我在上面的一个片段上搞砸了。当我到达我的工作计算机时,我将在REPL中进行验证。
另外,请查看Function Currying in Scala了解更多信息。