2014-10-08 87 views
1

Scala允許您使用下劃線來執行簡單的地圖。因此,例如,而不是書寫:Scala中的List.map中的下劃線和字符串連接

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

任何人都可以expla爲什麼?

+1

谷歌說你的問題在2011年回答http://stackoverflow.com/questions/7673545/usage-of-in-scala-lambda-functions你的 – 2014-10-08 21:10:53

+0

檢查[this](http://stackoverflow.com/問題/ 2173373/scala-foreach-strange-behavior)後。 – 2014-10-08 21:11:48

+0

感謝恩德,那個頁面上的答案很好地解釋了它。我想我會避免任何帶括號的表達式中的_字符(並希望我們的同行程序員)... – 2014-10-09 07:04:47

回答

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,因此括號內的部分被視爲分隔符te函數和下劃線_在此內部函數的範圍內解釋,而不是外部函數。

我真的不知道爲什麼List(1,2,3).map(println(_))的作品,但它似乎是其中由於單個說法似乎只是偶然的巧合工作的一些邊緣情況。我很樂意學習細節。無論如何,在帶有下劃線的匿名函數定義中使用括號是遲早會造成麻煩的,最好避免它。

+0

所以我終於弄清楚爲什麼'List(1,2,3).map(println(_)) '工作......在這種情況下'_'並不參考映射的參數 - 它將'println'變成**部分函數**,然後可以傳遞給map。 – 2014-10-16 19:45:18