2011-03-10 107 views
12

有人能解釋我究竟發生了什麼嗎?我沒有完全進入它現在:命名參數中的下劃線

val s = Seq(1D,2D,3D,4D) 
case class WithUnit(value: Double, unit: String) 
s map { WithUnit(_,"cm") } // works 
s map { WithUnit(value = _ , unit = "cm") } // error: missing parameter type for expanded function ((x$2) => value = x$2) 

我猜編譯不容推斷參數類型,因爲我寫的參數的名稱。但爲什麼不呢?僅僅因爲陳述參數的名字,不應該更困難?!

謝謝!

回答

27

當你寫道:

WithUnit(value = _, unit = "cm") 

你想它的意思是:

x => WithUnit(value = x, unit = "cm") 

但如果你在錯誤消息,仔細看,你會看到,編譯器沒有看到這樣的說法,它解析它作爲:

WithUnit(x => value = x, unit = "cm"}) 

正如你所看到的,放得更範圍的更緊密比你想要的。

_總是選擇最緊密的非簡併範圍。範圍在語法分析過程中完全由語法決定,而不考慮類型。

通過非退化的,我的意思是編譯器沒有覺得你的意思:

WithUnit(value = x => x, unit = "cm") 

最嚴格的非退化的範圍是指相對於下劃線最裏面的功能括號中定義的範圍。沒有這樣的規則,當函數調用嵌套時,編譯器將無法知道哪個_對應哪個函數。

+1

啊,我明白了!現在我有了更深的理解...... _tightest非退化範圍_ ...我會記住的!謝謝! – 2011-03-10 13:11:01

+1

可以說,這是一個錯誤。 WithUnit(_,「cm」)'因爲它被視爲一個部分應用的函數,而不是一個匿名函數文字。在與命名參數一起使用時,它不會得到相同的處理,我懷疑這只是一個疏忽。 – 2011-03-10 20:46:37

+1

@Daniel:我不認爲你在「部分應用函數」和「匿名函數文字」之間繪製的區別存在。 – 2011-03-10 21:03:00

3

嘗試這種情況:

scala> val withUnits = s map { x => WithUnit(value = x, unit = "cm") } 
withUnits: Seq[WithUnit] = List(WithUnit(1.0,cm), WithUnit(2.0,cm), WithUnit(3.0,cm), WithUnit(4.0,cm)) 

問題是下劃線的使用直接定義一個anynymous功能。

詳細描述在chapter 8.5. Placeholder syntax in the "Programming in Scala" book

+0

謝謝你的鏈接,有時會忘記檢查聖經;) – 2011-03-10 13:10:02