2016-07-29 3 views
5

Si f :: a -> b -> c est cari puis uncurry (f) peut être défini comme:Uncurry une Fonction cari de n paramètres en javascript

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

J'essaie d'implémenter la fonction ci-dessus en javascript. Est-ce que ma mise en œuvre ci-dessous est correcte et assez générique ou existe-t-il une meilleure solution?

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

Voici votre quatrième ou cinquième question de ces derniers jours. Je suppose que je suis curieux, pourquoi essayez-vous de faire tout cela * manuellement * au lieu d'utiliser Ramda? Sans compter que * tous * auraient pu être facilement résolus en jetant un coup d'œil sur le code source de Ramda. –

Répondre

2

Votre uncurry a trois problèmes:

  1. sinon tous les arguments attendus sont passés, il retourne une fonction cari (qui est pas le comportement d'une fonction normale, uncurried
  2. il ne peut pas traiter avec des arguments inutiles
  3. la mise en œuvre n'est pas très fonctionnel puisque vous ne réutilisez rien

Voici une approche plus fonctionnelle:

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 ne tient pas compte des arguments inutiles comme toute autre fonction en Javascript. Il réutilise uncurry, reduce et id.

Si trop peu d'arguments sont passés, une erreur se produit, car il n'est pas clair dans chaque cas quelle valeur doit être retournée (NaN, undefined).

1

Il est pas mal, mais on suppose que f est fonction jusqu'à ce que vous boucle à travers tous les arguments.

De même, si vous utilisez es6, utilisez l'opérateur repos au lieu de arguments. Et for ... of est une syntaxe plus agréable dans ES6 pour faire défiler les valeurs de tableau.

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