題目一:函數(shù)式編程當(dāng)中有個(gè)非常重要的概念就是 函數(shù)柯里化布讹,一個(gè)接受 任意多個(gè)參數(shù) 的函數(shù)字柠,如果執(zhí)行的時(shí)候傳入的參數(shù)不足梧田,那么它會(huì)返回新的函數(shù)萌业,新的函數(shù)會(huì)接受剩余的參數(shù),直到所有參數(shù)都傳入才執(zhí)行操作乡范。這種技術(shù)就叫柯里化配名,請(qǐng)你完成 curry 函數(shù)啤咽,它可以把任意的函數(shù)進(jìn)行柯里化,效果如下:
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)
// 這些函數(shù)執(zhí)行結(jié)果都一樣
例如:
const add = curry((a, b ,c ,d) => a + b + c +d)
add (1,2,3,4)=10
add(1)(2,3)(4)=10
add(1,2,3)(4)=10
add(1)(2)(3)(4)=10
題目二:不定參數(shù)處理
實(shí)現(xiàn)一個(gè)add方法段誊,使計(jì)算結(jié)果能夠滿足如下預(yù)期:
add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4)(5) = 15;
答案
首先函數(shù)柯里化因?yàn)閰?shù)固定闰蚕,使用vars數(shù)組保存每次傳進(jìn)來的參數(shù)栈拖,然后判斷fn的參數(shù)個(gè)數(shù)连舍,如果fn參數(shù)個(gè)數(shù)正好等于vars數(shù)組中保存的個(gè)數(shù),那么執(zhí)行fn涩哟,否則遞歸一次索赏,返回curried函數(shù),繼續(xù)等待輸入贴彼。這里外層curry 函數(shù)只會(huì)執(zhí)行一次便會(huì)被剝離潜腻,之后add會(huì)變成curried的一個(gè)引用,同時(shí)curried可以閉包引用外層的vars器仗,使得每次傳入的參數(shù)可以長(zhǎng)久保存融涣。
我的答案一:函數(shù)柯里化
const curry = (fn,vars=[]) =>{
const curried=(...args)=>{
for(let i of [...args]){
vars.push(i)
}
if(vars.length==fn.length){
return fn(...vars)
}else{
return curry(fn,vars)
}
}
return curried
}
網(wǎng)上更為優(yōu)秀的答案:用延展符將push做了簡(jiǎn)化
const curry = (f, args1 = []) => (...args2) => {
const args = [ ...args1, ...args2 ]
return f.length === args.length
? f(...args)
: curry(f, args)
}
參考上面網(wǎng)上優(yōu)秀答案的思路,寫出這個(gè)不定參數(shù)處理add函數(shù)精钮,...args可以接受不定參數(shù)威鹿,由于題目二中并沒有題目一中const add = curry((a, b ,c ,d) => a + b + c +d)
函數(shù)劫持的過程,所以不能直接返回函數(shù)定義轨香,而是要返回一個(gè)執(zhí)行完的函數(shù)curried(...args)忽你,同時(shí)在curried中再返回一個(gè)函數(shù)定義curried,這樣就可以把函數(shù)連接起來了臂容。由于參數(shù)不定科雳,這里對(duì)每次傳入的參數(shù)都要進(jìn)行執(zhí)行處理,執(zhí)行方法是利用函數(shù)的隱式轉(zhuǎn)換脓杉,當(dāng)函數(shù)執(zhí)行結(jié)束時(shí)會(huì)有一個(gè)toString的操作糟秘,來使函數(shù)能參與其他的運(yùn)算,這里我們將toString從新定義球散,返回vars中的累加值蚌堵,從而實(shí)現(xiàn)add運(yùn)算。
我的答案二:不定參數(shù)處理
const add=(...args)=>{
let vars=[]
const curried=(...c)=>{
vars=[...vars,...c]
return curried
}
curried.toString=()=>{
return vars.reduce((a,b)=>a+b,0)
}
return curried(...args)
}