2011-12-22 48 views
2

不知道如何正確地制定問題的問題,有一個在合併排序例如,從斯卡拉通過實例書69.函數定義爲頁面上鑽營的問題如下:斯卡拉的例子 - 與鑽營

def msort[A](less: (A, A) => Boolean)(xs: List[A]): List[A] = { 
    def merge(xs1: List[A], xs2: List[A]): List[A] = 
    if (xs1.isEmpty) xs2 
    else if (xs2.isEmpty) xs1 
    else if (less(xs1.head, xs2.head)) xs1.head :: merge(xs1.tail, xs2) 
    else xs2.head :: merge(xs1, xs2.tail) 
    val n = xs.length/2 
    if (n == 0) xs 
    else merge(msort(less)(xs take n), msort(less)(xs drop n)) 
} 

再有就是如何討好創建從它的其他功能的例子:

val intSort = msort((x : Int, y : Int) => x < y) 
val reverseSort = msort((x:Int, y:Int) => x > y) 

但是這兩條線給我關於數量不足的參數錯誤。如果我這樣做:

val intSort = msort((x : Int, y : Int) => x < y)(List(1, 2, 4)) 
val reverseSort = msort((x:Int, y:Int) => x > y)(List(4, 3, 2)) 

它會工作。爲什麼?有人可以解釋嗎?看起來這本書確實過時了,因爲它並不是第一例這樣的例子中的不一致。任何人都可以指出更真實的東西來閱讀嗎? (更好的免費電子書)。

回答

6

我的編譯器(2.9.1)同意,似乎這裏是一個錯誤,但編譯器告訴你該怎麼做:

error: missing arguments for method msort in object $iw; 
follow this method with `_' if you want to treat it as a partially applied function 

所以,這個工程:

val intSort = msort((x : Int, y : Int) => x < y) _ 

由於推斷出intSort的類型,因此編譯器似乎並不知道您是否打算部分應用,或者您是否錯過了參數。

當編譯器可以從預期的類型推斷部分應用的函數是預期的時,_可以省略。因此,這也工作:

val intSort: List[Int] => List[Int] = msort((x: Int, y: Int) => x < y) 

這顯然更詳細的,但更多的時候,你會利用這一點沒有任何多餘的樣板,例如,如果msort((x: Int, y: Int) => x < y)是參數到參數類型已經被稱爲是一個功能List[Int] => List[Int]


編輯:Scala Language Specification的當前版本的頁181提到的用於自Scala的2.0部分地施加方法與函數的隱式轉換的規則的緊固。有一個無效的例子代碼非常類似於斯卡拉的代碼,它被描述爲「先前的合法代碼」。

+0

哦,謝謝你,本!我只是在學習如何理解編譯器提示)基本上,你只是睜開眼睛看整個用例。 – noncom 2011-12-22 15:27:01

+0

讓斯卡拉開發者給出了他們爲什麼鼓勵下劃線表示部分應用函數的具體理由?從Haskell的背景來看,我覺得它很討厭;就好像函數在Scala中不是真正的頭等艙。 – 2011-12-22 17:26:22

+1

我在答案末尾提到的Scala語言規範頁面意味着假設是用戶更可能忘記了一個參數,而不是意圖部分應用。我不同意,因爲這隻適用於具有多個參數列表的方法,即currying必須在簽名中明確(而不是默認爲在Haskell中)。這種明確性意味着用戶應該知道期望什麼。 – 2011-12-23 10:28:44