Programmazione funzionale e invio di elementi all'array [chiuso]

0

Sto studiando la programmazione funzionale e sto facendo alcune domande sulla popolazione degli array.

In realtà, sto cercando di ricostruire la funzione Array.prototype.map, ed ecco cosa ho:

Array.prototype.map = function(callback) {
  let newArray = [];
  for (let item of this) {
    newArray.push(callback(item));
  }
  return newArray;
};

Funziona, bug Sto avendo qualche problema con il fatto che sono allocazione di memoria su ogni iterazione, il che significa che sto infrangendo i principi funzionali (senza riferimenti, solo cose nuove).

È vero quando si ha a che fare con gli array? Intendo, è corretto eseguire il loop e assegnare a un nuovo array?

    
posta Thomas thomas 18.01.2016 - 13:39
fonte

1 risposta

3

Il codice che ci si trova è il più lontano possibile da quello funzionale. L'intera funzione è costruita attorno a un ciclo di effetti collaterali che muta un valore.

Ecco l'implementazione funzionale banale di un'operazione map :

Array.prototype.map = function (fn) {
  const [first, ...rest] = this;
  return this.length === 0 ? [] : [fn(first)].concat(rest.map(fn));
};

Questo, tuttavia, farà esplodere lo stack per un array sufficientemente grande. Per evitare ciò, dobbiamo rendere la funzione ricorsiva in coda. Nella versione precedente, la coda è chiamata al metodo concat . La chiamata verrà ottimizzata, ma questo non ci aiuta molto: vogliamo che la chiamata ricorsiva a map sia la coda chiamata, in modo che it venga ottimizzato.

Il trucco standard per rendere una funzione ricorsiva in coda è introdurre un accumulatore che viene passato e quindi invertire il risultato.

Array.prototype.map = function (fn) {
  const mapTailrec = (ary, acc) => 
    ary.length === 0 ? 
      acc : 
      mapTailrec(ary.slice(0, -1), acc.concat([fn(ary[ary.length-1])]));
  return mapTailrec(this, []).reverse();
};

[Nota: in realtà sto barando qui, perché Array.prototype.reverse non è sfortunatamente trasparente referenziale. È è , tuttavia, è piuttosto semplice scrivere un% ca_de% di riferimento in modo ricorsivo in modo ricorsivo, quindi lascerò scorrere quella diapositiva.]

Come risulta, reverse è un metodo generale di iterazione: tutto ciò che può essere fatto con i loop può essere fatto con le pieghe, e quindi ogni operazione di raccolta è in realtà solo un caso speciale di fold :

Array.prototype.map = function (fn) {
  return this.reduce([], (acc, el) => acc.concat([fn(el)]));
};
    
risposta data 20.01.2016 - 12:28
fonte

Leggi altre domande sui tag