即使沒有專門學習過函式式的人也有可能聽說過傳說中的柯里化(currying),這是乙個比較 「出圈」 的概念,也是函式式程式設計的重要特性之一。
我會從最簡單的情況開始講述,剛開始你可能覺得無聊,但隨著函式的演化,事情會開始變得有趣。
下面請看乙個正常的 f# 函式:
let add x y = x + y
let three = add 1 2
上面這個 add 函式共有兩個引數 x 和 y,如果呼叫函式時給齊引數,它返回計算結果,如上所示,第一行定義了乙個函式 add, 第二行餵給它兩個引數 1 和 2, 它返回計算值 3
所謂柯里化,就是當呼叫該函式時我們只給它乙個引數,它就返回另乙個函式,像這樣:
let add1 = add 1
let three = add1 2
如上所示,我們給餵給 add 乙個引數(整數 1),它自然無法完成計算,如果是普通的命令式程式設計,這樣做會報錯,但在函式式裡,則會返回乙個新的函式 add1, 函式 add 缺少的那乙個引數就是 add1 的引數。
add 的型別是int -> int -> int
(前兩個 int 是引數,最後乙個 int 是返回值)
add1 的型別是(int -> int)
(是乙個函式)
如果給 add1 喂引數 2,此時引數齊了,會返回計算結果 3
另外,還可以這樣操作:
let addx x = add x
let add1 = addx 1
let three = add1 2
在上面的**中, addx 的型別是int -> (int -> int)
, 意思是 addx 這個函式接受乙個引數 int, 返回值是乙個函式(int -> int)
事情開始變得有趣了,還可以這樣操作:
let add x y = x + y
let addx x = add x
let addxy x y = addx x y
let three = addxy 1 2
addxy 的型別(函式簽名)是 int -> int -> int (正好與 add 的簽名一模一樣)
已知addxy x y = addx x y
, 同時已知addx x = add x
, 可得addxy x y = add x y
這正是 addxy 的簽名與 add 的簽名一模一樣的原因,他們的計算結果也是一樣的。
故事還沒有結束,下面繼續演化,是更有趣的事情。
在普通的命令式程式設計裡,加號+
是乙個運算子,但在 f# 裡,加號+
本質上是乙個函式!而x + y
其實是(+) x y
的語法糖!
也就是說,當我們寫下這句let add x y = x + y
, 事實上等於寫了let add x y = (+) x y
仔細觀察,不難發現,我們自己定義的函式add
, 與 f# 自帶的函式(+)
是一模一樣的。
本文到此結束,從最常見的情形出發,經過簡單而曲拆的柯里化變換之後,我們又回到了最初的地方,但經過這一小段旅程,我相信你和我一樣,再看同一行**,會有一種透過表象看到本質的感覺。
函式式程式設計之柯里化(curry)
函式式程式設計curry的概念 只傳遞給函式一部分引數來呼叫函式,然後返回乙個函式去處理剩下的引數。var add function x var increment add 1 increment 1 2 var addten add 10 addten 10 20 我們可以一次性的呼叫函式,也可以...
js函式式程式設計之柯里化(curry)
curry概念 只傳遞給函式一部分引數來呼叫它,讓它返回乙個函式去處理剩下的引數。你可以一次性地呼叫curry函式,也可以每次只傳乙個引數分多次呼叫。var add function x var increment add 1 var addten add 10 increment 2 3 addt...
Scala函式式程式設計 Curry柯里化
函式式程式設計的乙個思想 只傳遞給函式一部分引數來呼叫函式,然後返回乙個函式去處理剩下的引數。簡單說curry就是對高階函式 就是一種對過程的抽象 參考map它就是乙個抽象的過程 的降階處理。比如 function arg1,arg2 變成function arg1 arg2 function ar...