2016-07-29 71 views
5

若f ::甲 - >乙 - > c是咖喱然後uncurry(f)可被定義爲:Uncurry n個參數的函數咖喱在javascript

uncurry ::(甲 - >乙 - >Ç ) - >((a,b) - > c)

我試圖在javascript中實現上述功能。我的下面的實現是正確的還是通用的,還是有更好的解決方案?

const uncurry = f => { 
    if (typeof f != "function" || f.length == 0) 
    return f; 

    return function() 
    {  
    for (let i = 0; i < arguments.length; i++){ 
     f = f(arguments[i]); 
    } 

    return f; 
    }; 
} 


const curry = f => a => b => f(a, b); 
const curriedSum = curry((num1, num2) => num1 + num2); 
console.log(curriedSum(2)(3)); //5 

console.log(uncurry(curriedSum)(2, 3)); //5 
+1

這是你在過去幾天的第四或第五個問題。我想我很好奇,你爲什麼要手動完成所有這些*而不是使用Ramda?更不用說,他們中的所有*都可以通過查看Ramda源代碼輕鬆回答。 –

回答

2

uncurry有三個問題:

  1. 如果不是所有的預期參數傳遞它返回一個咖喱​​功能(這是不正常的,uncurried函數的行爲)
  2. 它不能處理不必要的參數
  3. 執行不了非常實用的,因爲你不重用任何

這裏是一個功能更強大的方法:

const id = x => x; 
 
const uncurry = f => (x, y) => f(x)(y); 
 

 
const uncurryn = n => f => (...xs) => { 
 
    const next = acc => xs => xs.reduce(uncurry(id), acc); 
 
    if (n > xs.length) throw new RangeError("too few arguments"); 
 
    return next(f) (xs.slice(0, n)); 
 
} 
 

 
const sum = x => y => z => x + y + z; 
 

 
try {uncurryn(3)(sum)(1, 2)} catch(e) {console.log(e.message)} 
 
console.log(uncurryn(3)(sum)(1, 2, 3)); 
 
console.log(uncurryn(3)(sum)(1, 2, 3, 4));

uncurryn忽略像Javascript中的任何其他功能不必要的爭議。它重用uncurry,reduceid

如果傳遞的參數太少,則會引發錯誤,因爲在每種情況下都不清楚應該返回哪個值(NaNundefined)。

1

這並不壞,但你認爲f是函數,直到你遍歷所有參數。

另外如果您使用es6考慮使用休息運算符而不是arguments。並且for ... of在es6中是更好的語法來循環訪問數組的值。

const uncurry = f => { 
 
    if (typeof f !== "function" || f.length == 0) 
 
    return f; 
 

 
    return (...args) => {  
 
    for (let arg of args) { 
 
     if (typeof f !== "function") { 
 
     return f; 
 
     } 
 
     
 
     f = f(arg); 
 
    } 
 

 
    return f; 
 
    }; 
 
} 
 

 

 

 

 
const curry = f => a => b => f(a, b); 
 
const curriedSum = curry((num1, num2) => num1 + num2); 
 
console.log(curriedSum(2)(3)); //5 
 

 
console.log(uncurry(curriedSum)(2, 3)); //5