2016-07-29 5 views
5

Wenn f :: a -> b -> c curried dann uncurry (f) ist, kann wie folgt definiert werden: -> B -> CUncurry a curried Funktion von n Parametern in JavaScript

uncurry :: (a) -> ((a, b) -> c)

Ich versuche, die obige Funktion in Javascript zu implementieren. Ist meine nachstehende Implementierung korrekt und generisch genug oder gibt es eine bessere Lösung?

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

Dies ist Ihre vierte oder fünfte Frage in den letzten Tagen in dieser Richtung. Ich glaube ich bin neugierig, warum versuchst du das alles * manuell * zu machen anstatt Ramda zu benutzen? Ganz zu schweigen davon, dass * alle * leicht durch einen Blick auf den Ramda-Quellcode beantwortet werden konnten. –

Antwort

2

Ihre uncurry hat drei Probleme:

  1. wenn nicht alle erwarteten Argumente übergeben werden eine curried Funktion gibt (was nicht das Verhalten eines normalen, uncurried Funktion ist)
  2. es kann nicht mit unnötigen Argumenten umgehen
  3. die Implementierung ist nicht sehr funktionell, da Sie nichts wiederverwenden Sie ist

hier ein funktioneller Ansatz:

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 unnötigen Argumente wie jede andere Funktion in Javascript ignoriert. Es verwendet uncurry, reduce und id.

Wenn zu wenige Argumente übergeben werden, wird ein Fehler ausgegeben, da in jedem Fall nicht klar ist, welcher Wert zurückgegeben werden soll (NaN, undefined).

1

Es ist nicht schlecht, aber man davon ausgehen, dass f ist Funktion, bis Sie eine Schleife durch alle Argumente.

Auch wenn Sie es6 verwenden, sollten Sie den Ruheoperator anstelle von arguments verwenden. Und for ... of ist schöner Syntax in es6, um Werte von Array zu durchlaufen.

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

Verwandte Themen