torna alle lezioni

Sommare con un numero arbitrario di parentesi

importanza: 2

Scrivete una funzione sum che funzioni in questo modo:

sum(1)(2) == 3; // 1 + 2
sum(1)(2)(3) == 6; // 1 + 2 + 3
sum(5)(-1)(2) == 6
sum(6)(-1)(-2)(-3) == 0
sum(0)(1)(2)(3)(4)(5) == 15

P.S. Aiuto: potresti impostare una conversione “toPrimitive” del tuo oggetto.

Apri una sandbox con i test.

  1. Per far si che che funzioni comunque, il risultato di sum deve essere una funzione.
  2. Questa funzione deve tenere in memoria il valore corrente.
  3. Come richiesto dall’esercizio, la funzione deve essere convertita in numero quando viene utilizzata con ==. Le funzioni sono oggetti, quindi la conversione avviene come descritto nel capitolo Conversione da oggetto a primitivi, e possiamo fornire un nostro metodo che si occupi di trasformare la funzione in tipo numerico.

Il codice:

function sum(a) {

  let currentSum = a;

  function f(b) {
    currentSum += b;
    return f;
  }

  f.toString = function() {
    return currentSum;
  };

  return f;
}

alert( sum(1)(2) ); // 3
alert( sum(5)(-1)(2) ); // 6
alert( sum(6)(-1)(-2)(-3) ); // 0
alert( sum(0)(1)(2)(3)(4)(5) ); // 15

Da notare che la funzione sum esegue una sola volta. Ritorna una funzione f.

Poi, in ogni chiamata successiva, f aggiunge il suo parametro alla somma presente in currentSum, e ritorna se stessa.

Non c’è ricorsione nell’ultima linea di f.

Una ricorsione appare in questo modo:

function f(b) {
  currentSum += b;
  return f(); // <-- chiamata ricorsiva
}

Nel nostro caso, semplicemente ritorniamo una funzione, senza effettuare alcuna chiamata:

function f(b) {
  currentSum += b;
  return f; // <-- non viene invocata, ritorna solamente se stessa
}

Questa f verrà utilizzata nella chiamata successiva, e ritornerà ancora se stessa, tutte le volte che sarà necessario. Quindi, quando la utilizzeremo come numero o stringa, toString ritorna la currentSum. Possiamo anche utilizzare Symbol.toPrimitive o valueOf per la conversione.

Apri la soluzione con i test in una sandbox.