偏函數和函數柯里化是JS函數式編程中的兩個重要概念,單獨看這兩個概念,能夠輕鬆的理解,可是把這兩個概念放到一塊兒,就糊塗了,搞不清楚二者的區別與聯繫。編程
我也是第一次嘗試弄清楚二者,若有錯誤,歡迎拍磚。bash
從一個數學概念函數開始。函數式編程
對於集合A中的任意元素(假設爲x),在集合B中都有惟一一個元素(假設爲y),知足某種對應關係(假設爲f),則這種對應關係就叫函數,記做y=f(x),x稱做函數的參數,y稱做函數的值。函數
能夠看出,函數是徹底對應的,即集合A中的每一個元素在集合B中都有對應值。可是,若是出現不徹底對應的狀況呢?學習
若是出現不徹底對應的狀況,好比下圖中集合A中的4,在集合B中沒有對應值ui
這種狀況下,咱們把這樣的對應關係就叫偏函數,集合A中可能有1個或多個元素沒有對應值(此時不是函數),也有可能有0個元素沒有對應值(此時是函數),因此說spa
偏函數不都是函數,但函數都是偏函數code
函數的參數能夠有多個,假設記做g=f(x,y) ,參數能夠看作一個有序對(x,y)的集合cdn
用JS代碼表述一下這個對應關係blog
function fn(x, y) {
if (x === 1 && y === 1) {
return 'a';
} else if (x === 1 && y === 2) {
return 'a';
} else if (x === 2 && y === 1) {
return 'b';
} else if (x === 2 && y === 2) {
return 'c';
}
}
複製代碼
第一,不要嫌哥的代碼Low;
第二,先不要把關鍵字function
叫作函數,暫且叫作對應關係
毫無疑問,對應關係fn
知足函數的概念,fn
是函數無疑。
同理,偏函數的參數也能夠有多個
用JS代碼表述一下這個對應關係
function partial(x, y) {
if (x === 1 && y === 1) {
return 'a';
} else if (x === 1 && y === 2) {
return 'a';
} else if (x === 2 && y === 1) {
return 'b';
}
}
複製代碼
集合A中的有序對(2,2)
沒有對應值,因此對應關係partial
是個偏函數。
看到了麼,偏函數不是其餘文章說的什麼固定了函數的某一個或幾個參數!,我參數數量不變仍能夠是偏函數。固然,若是咱們固定其中某一個或幾個參數,好比固定x就是1,對應關係fn
確定是偏函數
function fn(x, y) {
x = 1;
if (x === 1 && y === 1) {
return 'a';
} else if (x === 1 && y === 2) {
return 'a';
} else if (x === 2 && y === 1) {
return 'b';
} else if (x === 2 && y === 2) {
return 'c';
}
}
複製代碼
由於它只能描述部分對應關係(固然,若是集合A中把2開頭的有序對去掉,天然也是函數)
到這裏就應該清楚了,若是咱們把函數的某一個或某幾個參數固定,天然只能描述部分對應關係了(也有可能還是所有描述,好比上面集合A中的x固定爲1但把以2開頭的有序對去掉),這是一個充分沒必要要條件,因此固定參數的行爲,是偏函數的一個應用。
到這裏還沒明白偏函數的,找個隱蔽的地方,本身打本身屁屁吧!
下面看函數柯里化。
單獨理解函數柯里化也很簡單
把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,而且返回接受餘下的參數並且返回結果的新函數的技術。
上代碼,有一個求和函數
function sum (x, y, z) {
return x + y + z;
}
sum(1, 2, 3); // 6
複製代碼
使用lodash的柯里化方法
const curriedSum = _.curry(sum);
curriedSum(1)(2)(3); // 6
複製代碼
柯里化有2個要求
但在JS實際應用中,不少時候都不會嚴格遵照,請看lodash的柯里化方法,柯里化後容許接受多個參數
curriedSum(1, 2)(3); // 6
複製代碼
到這裏還沒明白函數柯里化的,找個隱蔽的地方,本身打本身屁屁吧!
1、這是兩個不一樣的概念,偏函數表達的是定義域和值域可能不徹底對應;函數柯里化指的是多參函數變換成單參函數的過程。
2、函數柯里化後,在調用的過程當中,出現了偏函數,仍是以上面求和函數爲例
function sum (x, y, z) {
return x + y + z;
}
const addOne = _.curry(sum);
const addTwo = addOne(1);
const addThree = addTwo(2);
const res = addThree(3);
複製代碼
sum
柯里化後的函數爲addOne
addTwo
是固定x爲1的偏函數addThree
是固定x爲1和y爲2的偏函數再次聲明:這是我第一次嘗試理清楚偏函數與函數柯里化的概念,不免出現錯誤,歡迎拍磚。
歡迎關注咱的微博,學習交流有個伴兒:@狂刀二
到這裏還沒關注咱微博的,找個隱蔽的地方,本身打本身屁屁吧!