Scala允许您使用下划线来执行简单的地图。例如,而不是写:
def roleCall(people: String*){
people.toList.map(x => println(x))
}
......我可以写一下:
def roleCall(people: String*){
people.toList.map(println(_))
}
但出于某种原因我不能写:
def greet(people: String*){
// This won't compile!
people.toList.map(println("Hello " + _))
}
相反,我必须写:
def greet(people: String*){
people.toList.map(x => println("Hello " + x))
}
任何人都可以解释原因吗?
答案 0 :(得分:1)
基本上,只有在没有嵌套括号的情况下,函数定义的简写语法才能正常工作。这是因为每个嵌套级别都会创建自己的下划线所在的范围。在REPL中,您可以检查例如:
scala> val list = List(1,2,3).map(_ + 1)
list: List[Int] = List(2, 3, 4)
和
scala> val list = List(1,2,3).map((_ + 1))
list: List[Int] = List(2, 3, 4)
两者都有效,但是一旦在括号后添加任何内容,就会出现错误:
val list = List(1,2,3).map((_ + 1) + 1)
<console>:58: error: missing parameter type for expanded function ((x$1) => x$1.$plus(1))
val list = List(1,2,3).map((_ + 1) + 1)
如您所见,错误仅与函数(_ + 1)(在消息中显示为((x$1) => x$1.$plus(1))
)有关,而不是与整个表达式(_ + 1) + 1
有关,因此括号中的部分被视为一个单独的函数,下划线_
在这个内部函数的范围内解释,而不是外部函数。
我不确定为什么List(1,2,3).map(println(_))
有效,但似乎是一些边缘情况,由于单一论证似乎仅仅是巧合。我很高兴自己能够了解细节。无论如何,在带有下划线的匿名函数定义中使用括号肯定会迟早引起麻烦,最好避免它。