2016-09-21 49 views
2

有人可以解釋爲什麼r1類型是:(String => String, String)但是r2類型是String => (String, String)?謝謝。scala - 部分應用函數的元組類型

def f1(n: String, m: String): String = m + n 
val f2: String => String = f1(_, "something") 
val r1: (String => String, String) = f2 -> "foo" 
val r2: String => (String, String) = f1(_, "something") -> "foo" 

回答

0

即使在閱讀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"

+0

謝謝。現在對我來說很有意義。 – limuhob

3

讓我們來看看在place holder語法會發生什麼匿名函數:

val f2: String => String = f1(_, "something") 

其展開:(x$1: String) => f1(x$1, "something")"(先從scala -Xprint:typer您REPL)

隨着f2 -> "foo",它只是變得(f2,"foo")和因此(String => String, String)

f1(_, "something") -> "foo",其被評估爲:

(x:String) => f1(x,"something") -> foo 
(x:String) => (f1(x,"something") , foo) 
(String => (String, String)) 

如果佔位符的原因首先評估的混亂呢?

評估佔位符並在編譯時調整樹。與->一樣,由於ArrayAssoc隱含,所以在運行時將其評估爲元組a。

+0

嗯謝謝! – limuhob

相關問題