Aggiunta di proprietà dell'oggetto mediante la programmazione funzionale

0

Attualmente sto imparando la programmazione funzionale usando Underscore.js. Quello che voglio fare è aggiungere due coordinate insieme. Sia P1 = (0, 0) e P2 = (1, 1). Pertanto, P1 + P2 = (1, 1)

Ho una soluzione, ma sembra così complicata che sono sicuro di fare qualcosa di sbagliato:

// Base 2D Cartesian Point
var Point = function(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.add = function(delta) {
  return _.object(_.keys(this),
    _.map(
      _.zip(
        _.values(this), 
        _.values(delta)), 
        function(point) {
          return _.reduce(point, 
            function(memo, num) { return memo + num; }, 0);
        }
    )
  );
}

Questa è l'implementazione corretta della funzione di aggiunta per i punti che utilizza Underscore.js o esiste una soluzione migliore?

    
posta Pete 22.02.2014 - 05:28
fonte

3 risposte

1

Imparare la programmazione funzionale non significa dimenticare ciò che già sai. Per le coordinate bidimensionali fisse, vorrei solo usare quanto segue:

sum = [p1[0] + p2[0], p1[1] + p2[1]]

Se non conosci la dimensione delle tue coordinate, o se è grande, il prossimo migliore in questo caso è usare una comprensione della lista , che per qualche motivo molte persone dimenticano , o non pensare che sia "abbastanza funzionale", perché assomiglia a un ciclo for. Tuttavia, è più potente di un ciclo for poiché è un'espressione che può essere assegnata, può essere valutata pigramente ed è parallelizzabile se non si introducono effetti collaterali.

sum = (p1[i] + p2[i] for i in [0..(p1.length - 1)])

Se avessi un sacco di cose da fare, come addizione, sottrazione, moltiplicazione, ecc. in genere creeresti una funzione per eseguire l'iterazione, che prende un'altra funzione come argomento per ciò che vuoi fare a ogni coppia. Sarebbe come questo:

corresponding = (p1, p2, f) -> f(p1[i], p2[i]) for i in [0..(p1.length - 1)]

E lo useresti in questo modo:

sum  = corresponding(p1, p2, (i, j) -> i + j)
diff = corresponding(p1, p2, (i, j) -> i - j)
prod = corresponding(p1, p2, (i, j) -> i * j)

Certo, non è molto più breve della comprensione delle liste, ma una funzione corresponding del mondo reale sarebbe probabilmente molto più lunga a causa della gestione degli errori.

Tieni presente che questi esempi si trovano in CoffeeScript , poiché non conosco underscore.js, ma le soluzioni sono abbastanza tipici della programmazione funzionale.

    
risposta data 22.02.2014 - 09:31
fonte
2

Se hai intenzione di fare programmazione funzionale sui punti, sarebbe più sensato che i tuoi punti fossero elenchi di coordinate anziché oggetti. Questo semplifica il codice un po ':

function add(p1, p2) {
    _.map(_.zip(p1, p2), function(coords) {
        return _.reduce(coords, function(coord, sum) { return sum + coord; }, 0);
    });
}

Questo può avere senso se hai a che fare con lo spazio a dieci dimensioni, ma sembra eccessivo per due dimensioni.

    
risposta data 22.02.2014 - 06:37
fonte
0

Esistono diversi metodi che è possibile utilizzare per eseguire questo calcolo. Utilizzerò il tuo oggetto base 2D e lo estenderò in due modi

// Base 2D Cartesian Point
var Point = function(x, y) {
  this.x = x;
  this.y = y;
};

Poiché il suggerimento di Robert Harvey è così semplice, iniziamo con questo:

var startpoint = new Point(0, 0);
var offsetpoint = new Point(startpoint.x + 5, startpoint.y + 5);

Successivamente, puoi aggiungere una funzione all'istanza Point già creata:

Point.add = function(x, y) {
  this.x += x;
  this.y += y;
};

Come hai mostrato sopra, puoi anche modificare il prototipo di classe cambiando Point.add in Point.prototype.add . La dichiarazione rivista aggiunge il metodo add a tutte le istanze Point.

Supponiamo di voler passare un punto invece di x e y? Possiamo farlo anche noi. Non possiamo semplicemente usare una dichiarazione del metodo polimorfico. Possiamo, tuttavia, trasformare la funzione in una nuova funzione con parametri diversi. Il lato negativo di questo è che, da quel momento in poi, non sarai mai in grado di tornare alla prima implementazione con x e y senza sostituire di nuovo la funzione. Probabilmente è troppo per ora. Aggiungiamo la prossima versione:

Point.prototype.addPoint = function(anotherPoint) {
    // Is the object being passed in of our class?
    if(anotherPoint instanceof Point) {
      this.add(anotherPoint.x, anotherPoint.y);
    }
};

Ecco un jsfiddle con questo codice funzionante.

    
risposta data 22.02.2014 - 07:07
fonte

Leggi altre domande sui tag