即使在閱讀Jatin的回答後,有些事情讓我感到困惑。這是我進一步研究後的發現。請注意,爲了節省輸入,我不在左側使用類型歸屬,並讓Scala來推斷。
def f1(n: String, m: String): String = m + n
// f1: (n: String, m: String)String
val f2 = f1(_, "something")
通常,強調在「表達」表示,其是由編譯器適當擴大匿名函數。如果編譯器找不到合適的'下劃線'參數類型,它會像下面這樣抱怨:
// <console>:12: error: missing parameter type for expanded function ((x$1) => f1(x$1, "something"))
val f2 = f1(_:String, "something") // Specifiying the type of the `_` as `_:String` fixes the missing parameter type error above.
// f2: String => String = <function1>
val r1 = f2 -> "foo"
// r1: (String => String, String) = (<function1>,foo)
現在是重要的東西。爲什麼下面的行不會給出與上面的r1相同的結果!!!在underscore scoping rules.
val r2 = f1(_:String, "something") -> "foo"
// r2: String => (String, String) = <function1>
其原因在於由丹尼爾出色答卷據丹尼爾回答的第1章,匿名函數的範圍將包括整個右側的表達。所以上面的擴展匿名函數將
(x:String) => f1(x:String, "something") -> "foo"
這給函數簽名字符串=>(字符串,字符串)
爲了解決這個問題,我們使用的第二個規則索布拉爾的答案和限制)由包圍所述f1
表達(綁定到_
匿名函數或{},像下面的範圍:
val r3 = (f1(_:String, "something")) -> "foo"
r3: (String => String, String) = (<function1>,foo)
現在,我們得到相同的結果作爲val r1 = f2 -> "foo"
謝謝。現在對我來說很有意義。 – limuhob