一. No1.柯里化(currying)與部分應(yīng)用(partial application)
柯里化(currying)
柯里化是使一個(gè)函數(shù)
f: X * Y -> R
轉(zhuǎn)變?yōu)?br>
f’: X -> (Y -> R)
與用兩個(gè)參數(shù)調(diào)用f不同,我們用一個(gè)參數(shù)運(yùn)行f’。返回的結(jié)果是一個(gè)函數(shù)褂乍,然后用第二個(gè)參數(shù)調(diào)用此函數(shù)轰豆,得到結(jié)果寡润。
如此赴邻,如果未柯里化的函數(shù)f這樣調(diào)用
f(3,5)
柯里化后的函數(shù)f’是這樣調(diào)用的
f(3)(5)
比如: 未柯里化的函數(shù)add()
function add(x, y) { return x + y;}add(3, 5); // returns 8
柯里化后的add()
function addC(x) { return function (y) { return x + y; }}addC(3)(5); // returns 8
柯里化的規(guī)則
柯里化將一個(gè)二元函數(shù)书闸,轉(zhuǎn)變?yōu)橐辉瘮?shù)审胸,這個(gè)函數(shù)將返回另一個(gè)一元函數(shù)亥宿。
curry: (X × Y → R) → (X → (Y → R))
Javascript Code:
function curry(f) { return function(x) { return function(y) { return f(x, y); } }}
部分應(yīng)用(partial application)
部分應(yīng)用將一個(gè)函數(shù)
f: X * Y -> R
的第一個(gè)參數(shù)固定而產(chǎn)生一個(gè)新的函數(shù)
f`: Y -> R
f’與f不同,只需要填寫第二個(gè)參數(shù)砂沛,這也是f’比f少一個(gè)參數(shù)的原因烫扼。
比如:將函數(shù)add的第一個(gè)參數(shù)綁定為5來產(chǎn)生函數(shù)plus5。
function plus5(y) { return 5 + y;}plus5(3); // returns 8
部分應(yīng)用的規(guī)則
部分應(yīng)用使用一個(gè)二元函數(shù)和一個(gè)值產(chǎn)生了一個(gè)一元函數(shù)碍庵。
partApply : ((X × Y → R) × X) → (Y → R)
Javascript Code:
function partApply(f, x) { return function(y) { return f(x, y); }}
No2.優(yōu)化嵌套的條件語句
我們?cè)鯓觼硖岣吆蛢?yōu)化javascript里嵌套的if語句呢映企?
if (color) { if (color === 'black') { printBlackBackground(); } else if (color === 'red') { printRedBackground(); } else if (color === 'blue') { printBlueBackground(); } else if (color === 'green') { printGreenBackground(); } else { printYellowBackground(); }}
一種方法來提高嵌套的if語句是用switch語句。雖然它不那么啰嗦而且排列整齊静浴,但是并不建議使用它堰氓,因?yàn)檫@對(duì)于調(diào)試錯(cuò)誤很困難。這告訴你為什么苹享。
switch(color) { case 'black': printBlackBackground(); break; case 'red': printRedBackground(); break; case 'blue': printBlueBackground(); break; case 'green': printGreenBackground(); break; default: printYellowBackground();}
如果可以重構(gòu)的話双絮,我們可以試著簡(jiǎn)化函數(shù)。比如不需要為每個(gè)顏色寫一個(gè)函數(shù)得问,而是將顏色作為函數(shù)的參數(shù)囤攀。
function printBackground(color) { if (!color || typeof color !== 'string') { return; }}
但是如果不能重構(gòu)的話,我們必須避免過多的條件檢查宫纬,避免過多使用switch抚岗。我們必須考慮最有效率的方法,使用object哪怔。
let colorObj = { 'black': printBlackBackground, 'red': printRedBackground, 'blue': printBlueBackground, 'green': printGreenBackground, 'yellow': printYellowBackground};if (color in colorObj) { colorObjcolor;}
No3.運(yùn)用存儲(chǔ)加速遞歸
大家對(duì)斐波那契(Fibonacci)數(shù)列都很熟悉宣蔚。我們可以再20秒內(nèi)寫出下面這樣一個(gè)方法向抢。
var fibonacci = function(n){ return n < 2 ? n : fibonacci(n-1) + fibonacci(n-2);}
它可以運(yùn)行,但并不高效胚委。它做了太多重復(fù)的運(yùn)算挟鸠,我們可以通過存儲(chǔ)這些運(yùn)算結(jié)果來使其加速。
var fibonacci = (function() { var cache = [0, 1]; // cache the value at the n index return function(n) { if (cache[n] === undefined) { for (var i = cache.length; i <= n; ++i) { cache[i] = cache[i-1] + cache[i-2]; } } return cache[n]; }})()
我們也可以定義一個(gè)高階函數(shù)亩冬,它接收一個(gè)方法作為參數(shù)艘希,返回一個(gè)該方法運(yùn)用存儲(chǔ)后的新方法。
var memoize = function(func){ var cache = {}; return function(){ var key = Array.prototype.slice.call(arguments).toString(); return key in cache ? cache[key] : (cache[key] = func.apply(this,arguments)); }}fibonacci = memoize(fibonacci);
ES6版本的memoize函數(shù)如下:
var memoize = function(func){ const cache = {}; return (...args) => { const key = [...args].toString(); return key in cache ? cache[key] : (cache[key] = func(...args)); }}fibonacci = memoize(fibonacci);
我們可以將memoize()用在很多其他地方
GCD(最大公約數(shù))
var gcd = memoize(function(a,b){ var t; if (a < b) t=b, b=a, a=t; while(b != 0) t=b, b = a%b, a=t; return a;})gcd(27,183); //=> 3階乘運(yùn)算
var factorial = memoize(function(n) { return (n <= 1) ? 1 : n * factorial(n-1);})factorial(5); //=> 120
Original:[Js Tips - A JavaScript tip per day!*
") 0px 2px / cover;">*](Js Tips - A JavaScript tip per day!*
") 0px 2px / cover;">*)