FP入門概念必須掌握的是“純函數”,“柯里化”,“函數組合”。就算只是作為一個FP新手,理解柯里化也是基本的要求。但是我對柯里化的理解一直很模糊,那么今天寫個總結,搞定它。
模糊在哪?
不知道什么是真正的柯里化,對柯里化的理解就是減少一個接收的參數,反柯里化就是添加一個接收的參數(我相信大多數人和我是一樣一樣的)。這種理解其實是非常粗淺的。
首先上Wiki:
柯里化
柯里化(英語:Currying),又譯為卡瑞化或加里化,是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,并且返回接受余下的參數而且返回結果的新函數的技術。
在直覺上,柯里化聲稱“如果你固定某些參數,你將得到接受余下參數的一個函數”。
這不還是等于什么都沒說嘛! 還是用ScriptOJ的一道題目來理解理解。
curry函數
Q:
函數式編程當中有一個非常重要的概念就是 函數柯里化。一個接受 任意多個參數 的函數,如果執行的時候傳入的參數不足,那么它會返回新的函數,新的函數會接受剩余的參數,直到所有參數都傳入才執行操作。這種技術就叫柯里化。請你完成 curry
函數,它可以把任意的函數進行柯里化,效果如下:
const f = (a, b, c d) => { ... }
const curried = curry(f)?
curried(a, b, c, d)
curried(a, b, c)(d)
curried(a)(b, c, d)
curried(a, b)(c, d)
curried(a)(b, c)(d)
curried(a)(b)(c, d)
curried(a, b)(c)(d)
// ...
// 這些函數執行結果都一樣
?// 經典加法例子
const add = curry((a, b) => a + b)
const add1 = add(1)?
add1(1) // => 2
add1(2) // => 3
add1(3) // => 4
注意,傳給 curry
的函數可能會有任意多個參數。
這道題的意思其實就是,不管我傳進去幾個函數,得到的答案都是相同的。它產生了一系列函數方法,每個函數都只有一個參數,實現是通過每次在另一個新的Curry函數中隱藏一個參數來實現。這種思想大概就是化繁為簡,分而治之?
怎么理解呢?
如果我定義一個函數,需要a,b,c,d四個參數,那么如果想要程序正常跑起來,就得給它傳四個參數,一個都不能少,否則就會報錯。那么,如果我們把它柯里化了呢?那么來解答一下這道題:
var curry=function curry(f)
{? var arr=arguments.length>1 && argument[1]!==undefined?arguments[1]:[];
//參數的個數是否大于1或第2個參數不等于undefined?是的話,arr為第2個參數,否的話,arr為空數組
return function f1(){
//返回一個函數f1
for (var len=arguments.length,args=Array(len),i=0;i<len;i++){? args[i]=arguments[i];
//遍歷argument,將其參數存入arg[]中 }?
return function f2(a){
//返回一個函數f2
return a.length === f.length ? f(a):curry(f,a)};
//a的長度是否等于f的長度?是的話,f2為f(a);否,f2為curry(f,a)(重新調用一次curry)
}([].concat(arr,args));
//將arr,args連接起來};
然后抄一下別人的代碼:
ES6:(果然簡潔):
const curry = (f, arr = []) => {
return (...args) => {
return (a) => {
return a.length === f.length ? f(a) : curry(f, a);
}([...arr, ...args]);
};
};
老司機系列:
curry(f, a))([...arr, ...args]);```
老司機系列寫的就很有靈性了...看起來我ES6還完全沒入門啊,多多加油:)