2012-09-27 54 views
0

我只是在看講座2.2高階函數(對於Functional programming principles in Scala)。在那裏,一個求和函數的定義如下:這兩個函數定義是否等價?

def sum(f: Int => Int, a: Int, b: Int) { ... } 

後來,同樣的函數定義是這樣的:

def sum(f: Int => Int)(a: Int, b: Int) { ... } 

他們似乎是等價的,但沒有給出解釋爲什麼要選擇在結束了。

+0

另外值得注意的是,當您使用仿製藥,仿製類型參數一次綁定一個參數塊。所以如果你定義了f [A](x:A,y:A),那麼將選擇A來匹配'x'和'y'的類型,而'def f [A](x: A)(y:A)'表示'A'的類型將是'x'的類型,並且'y'具有更好的匹配。這兩種行爲都可能有用。 –

回答

2

第二個定義聲明瞭一個具有兩個參數列表的方法。忽略implicits,那麼通常用於啓用功能應用程序curried。基本的想法是,你可以綁定一些函數的參數,這會產生一個剩餘參數較少的另一個函數,即那些尚未綁定的參數。下面是一個簡單的文本書例如:

def add(xs: List[Int])(y: Int) = 
    xs.map(_ + y) 

// Bind first argument and store resulting function in f 
val f = add(List(2,3,5,7,11))_ 

println(f(0)) // List(2, 3, 5, 7, 11) 
println(f(10)) // List(12, 13, 15, 17, 21) 

// Bind first argument and store resulting function in g 
val g = add(List(0,1,0,1,0,1))_ 

println(g(1)) // List(1, 2, 1, 2, 1, 2) 
println(g(-1)) // List(-1, 0, -1, 0, -1, 0) 

// Regular invocation 
println(add(List(1,2,3))(4)) // List(5, 6, 7) 

你會發現很多的文章在網上左右討好,例如,如何使用currying in Scala,或者說有multiple ways to curry in Scala

關於爲什麼選擇over:在Haskell中,基本上總是選擇curried版本而不是uncurried版本,因爲後者給了你能夠部分綁定參數的優勢,並且因爲沒有「語法懲罰「或使用咖喱版本的運行時間損失。由於Scala並非如此(正如您可以從上面的代碼片段中看到的那樣),您可能想要更喜歡uncurried樣式,除非您知道您的方法/函數最有可能的用例是benefit from currying

1

排序,但不完全。最大的區別在於擁有多個參數列表可以讓我們更輕鬆地使用該功能,而無需指定所有參數。

舉一個例子,讓我們這樣定義你的兩個功能:

現在,讓我們定義一個函數g這需要作爲參數,另一個函數,它有兩個Int S和產生Int

def g(f: (Int, Int) => Int) = f(3, 5) 

帶有多個參數列表的sum版本允許我們只指定第一個列表的參數,然後將這個部分應用的函數傳遞給g

g(sum2(_ + 1)) 

這很簡單,很乾淨。

沒有單獨的參數列表,如sum1,我們必須寫一個lambda表達式來表示,其中ab參數來自:

g((a: Int, b: Int) => sum1(_ + 1, a, b)) 
相關問題