web-dev-qa-db-fra.com

Fonction somme au curry variadic

J'ai besoin d'une fonction js sum pour fonctionner comme ceci:

sum(1)(2) = 3
sum(1)(2)(3) = 6
sum(1)(2)(3)(4) = 10 
etc.

J'ai entendu dire que ça ne pouvait pas être fait. Mais entendu que si l'ajout de + devant sum peut être fait . Comme +sum(1)(2)(3)(4)
Des idées sur la façon de faire cela?

20
Yaroslav Yakovlev

Je ne sais pas si j'ai compris ce que vous voulez, mais

function sum(n) {
  var v = function(x) {
    return sum(n + x);
  };

  v.valueOf = v.toString = function() {
    return n;
  };

  return v;
}

console.log(+sum(1)(2)(3)(4));

JsFiddle

60
Rafael

Voici un exemple d'utilisation de crochets vides dans le dernier appel en tant que touche rapprochée (de ma dernière interview):

somme (1) (4) (66) (35) (3) ()

function sum(numberOne) {
  var count = numberOne;
  return function by(numberTwo) {
    if (numberTwo === undefined) {
      return count;
    } else {
      count += numberTwo;
      return by;
    }
  }
}
console.log(sum(1)(4)(66)(35)(3)());

10
yury.hrynko

Je publie cette révision comme sa propre publication, car je n'ai apparemment pas encore assez de réputation pour la laisser en commentaire. Ceci est une révision de l'excellente solution de @Rafael. 

function sum (n) {
    var v = x => sum (n + x);
    v.valueOf = () => n; 
    return v;
}

console.log(+sum(1)(2)(3)(4)); //10

Je n'ai vu aucune raison de conserver le bit v.toString, car cela ne semblait pas nécessaire. Si je me suis trompé, merci de me le faire savoir dans les commentaires, pourquoi v.toString est nécessaire Converti le reste des fonctions anonymes en fonctions de flèche pour faciliter la lecture. 

5
Brad

Voici une solution utilisant ES6 et toString, similaire à @Vemba

function add(a) {
  let curry = (b) => {
    a += b
    return curry
  }
  curry.toString = () => a
  return curry
}

console.log(add(1))
console.log(add(1)(2))
console.log(add(1)(2)(3))
console.log(add(1)(2)(3)(4))

1
Artokun

Vous pouvez utiliser la fonction ci-dessous

function add(num){
   add.sum || (add.sum = 0) // make sure add.sum exists if not assign it to 0
   add.sum += num; // increment it
   return add.toString = add.valueOf = function(){ 
      var rtn = add.sum; // we save the value
      return add.sum = 0, rtn // return it before we reset add.sum to 0
   }, add; // return the function
}

Les fonctions étant des objets, nous pouvons y ajouter des propriétés, que nous réinitialisons lorsqu’il a été consulté.

1
Amit Joki

Voici une solution avec une fonction générique de curry variadic dans ES6 Javascript, avec l’avertissement qu’un final () est nécessaire pour invoquer les arguments:

const curry = (f) =>
   (...args) => args.length? curry(f.bind(0, ...args)): f();
const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1)() == 5 // true

En voici un autre qui n'a pas besoin de (), en utilisant valueOf comme dans la réponse de @ rafael . J'ai l'impression qu'utiliser valueOf de cette manière (ou peut-être même du tout) est très déroutant pour les lecteurs de votre code, mais chacun pour leur propre compte.

La toString dans cette réponse est inutile. En interne, lorsque javascript effectue une coersion de types, il appelle toujours valueOf() avant d'appeler toString().


// invokes a function if it is used as a value
const autoInvoke = (f) => Object.assign(f, { valueOf: f } );

const curry = autoInvoke((f) =>
   (...args) => args.length? autoInvoke(curry(f.bind(0, ...args))): f());

const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1) + 0 == 5 // true
0
user1034533

Une autre approche légèrement plus courte:

 const sum = a => b => b? sum(a + b) : a;

Utilisable comme:

console.log(
  sum(1)(2)(),
  sum(3)(4)(5)()
);
0
Jonas Wilms

Pour que sum(1) soit appelable en tant que sum(1)(2), il doit renvoyer une fonction.

La fonction peut être appelée ou convertie en un nombre avec valueOf.

function sum(a) {

   var sum = a;
   function f(b) {
       sum += b;
       return f;
    }
   f.toString = function() { return sum }
   return f
}
0
Vemba