我只是在看講座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) { ... }
他們似乎是等價的,但沒有給出解釋爲什麼要選擇在結束了。
我只是在看講座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) { ... }
他們似乎是等價的,但沒有給出解釋爲什麼要選擇在結束了。
第二個定義聲明瞭一個具有兩個參數列表的方法。忽略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 。
排序,但不完全。最大的區別在於擁有多個參數列表可以讓我們更輕鬆地使用該功能,而無需指定所有參數。
舉一個例子,讓我們這樣定義你的兩個功能:
現在,讓我們定義一個函數g
這需要作爲參數,另一個函數,它有兩個Int
S和產生Int
def g(f: (Int, Int) => Int) = f(3, 5)
帶有多個參數列表的sum
版本允許我們只指定第一個列表的參數,然後將這個部分應用的函數傳遞給g
:
g(sum2(_ + 1))
這很簡單,很乾淨。
沒有單獨的參數列表,如sum1
,我們必須寫一個lambda表達式來表示,其中a
和b
參數來自:
g((a: Int, b: Int) => sum1(_ + 1, a, b))
另外值得注意的是,當您使用仿製藥,仿製類型參數一次綁定一個參數塊。所以如果你定義了f [A](x:A,y:A),那麼將選擇A來匹配'x'和'y'的類型,而'def f [A](x: A)(y:A)'表示'A'的類型將是'x'的類型,並且'y'具有更好的匹配。這兩種行爲都可能有用。 –