1

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))
}

谁能解释为什么?

4

1 回答 1

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(_))有效,但它似乎是一些边缘情况,由于单一参数似乎只是巧合。我很高兴自己了解细节。无论如何,在带有下划线的匿名函数定义中使用括号迟早会造成麻烦,最好避免它。

于 2014-10-08T22:09:49.360 回答