Domanda

Ho lavorato con node.js per un po 'su una chat app (lo so, molto originale, ma ho pensato che sarebbe stato un buon progetto di apprendimento). Underscore.js fornisce un sacco di concetti di programmazione funzionali che sembrano interessanti, quindi mi piacerebbe capire come un programma funzionale in JavaScript sarebbe messa a punto.

Dalla mia comprensione della programmazione funzionale (che può essere sbagliato), l'idea è quella di effetti collaterali evitare, che sono fondamentalmente avendo una funzione che aggiorna un altro al di fuori variabili della funzione in modo da qualcosa come

var external;
function foo() {
   external = 'bar';
}
foo();

sarebbe la creazione di un effetto collaterale, giusto? Quindi, come regola generale, si vuole evitare di disturbare le variabili in ambito globale.

Ok, quindi come funziona quando hai a che fare con gli oggetti e cosa no? Ad esempio, un sacco di volte, avrò un costruttore e un metodo init che inizializza l'oggetto, in questo modo:

var Foo = function(initVars) {
   this.init(initVars);
}

Foo.prototype.init = function(initVars) {
   this.bar1 = initVars['bar1'];
   this.bar2 = initVars['bar2'];
   //....
}

var myFoo = new Foo({'bar1': '1', 'bar2': '2'});

Quindi il mio metodo init è intenzionalmente causando effetti collaterali, ma che sarebbe un modo funzionale per gestire lo stesso tipo di situazione?

Inoltre, se qualcuno mi potrebbe indicare sia un codice sorgente Python o JavaScript di un programma che cerca di essere il più funzionale possibile, che sarebbe anche molto apprezzato. Mi sento come se fossi vicino al "ottenerlo", ma io sono solo non del tutto lì. Principalmente mi interessa come funzionale programmazione funziona con la tradizionale concetto di classi OOP (o lo fa franca per qualcosa di diverso, se questo è il caso).

È stato utile?

Soluzione

È necessario leggere questa domanda:

JavaScript come linguaggio funzionale

Ci sono un sacco di link utili, tra cui:

Ora, la mia opinione. Un sacco di gente comprendono male JavaScript , forse perché il suo aspetto di sintassi come molti altri linguaggi di programmazione (dove Lisp / Haskell / OCaml aspetto completamente diverso). JavaScript è non object-oriented, è in realtà un prototipo a base di lingua . Non ha le classi o eredità classica quindi non dovrebbe davvero essere rispetto a Java o C ++.

JavaScript può essere migliore rispetto a un Lisp; ha chiusure e le funzioni di prima classe. Il loro utilizzo è possibile creare altre tecniche di programmazione funzionali quali applicazione parziale ( accattivarsi).

Facciamo un esempio (utilizzando sys.puts da node.js):

var external;
function foo() {
    external = Math.random() * 1000;
}
foo();

sys.puts(external);

Per sbarazzarsi di effetti collaterali a livello globale, siamo in grado di avvolgerlo in una chiusura:

(function() {
    var external;
    function foo() {
        external = Math.random() * 1000;
    }
    foo();

    sys.puts(external);
})();

Si noti che non possiamo realmente fare nulla con external o foo al di fuori del campo di applicazione. Sono completamente avvolti nel loro chiusura, intoccabile.

Ora, per sbarazzarsi del external effetto collaterale:

(function() {
    function foo() {
        return Math.random() * 1000;
    }

    sys.puts(foo());
})();

Alla fine, l'esempio non è puramente funzionale poiché non possono essere. Utilizzando un numero casuale legge dallo stato globale (per ottenere un seme) e la stampa per la console è un effetto collaterale.

voglio anche sottolineare che la miscelazione programmazione funzionale con gli oggetti è perfettamente bene. Prendete questo esempio:

var Square = function(x, y, w, h) {
   this.x = x;
   this.y = y;
   this.w = w;
   this.h = h;
};

function getArea(square) {
    return square.w * square.h;
}

function sum(values) {
    var total = 0;

    values.forEach(function(value) {
        total += value;
    });

    return total;
}

sys.puts(sum([new Square(0, 0, 10, 10), new Square(5, 2, 30, 50), new Square(100, 40, 20, 19)].map(function(square) {
    return getArea(square);
})));

Come si può vedere, utilizzando gli oggetti in un linguaggio funzionale può essere più che bene. Alcuni Lisps hanno nemmeno le cose chiamati elenchi di proprietà che possono essere pensati come oggetti.

Il vero trucco per utilizzare gli oggetti in uno stile funzionale è quello di assicurarsi che non si basano sui loro effetti collaterali, ma invece li trattano come immutabile. Un modo semplice è ogni volta che si desidera modificare una proprietà, basta creare una nuovo oggetto con i nuovi dettagli e passare che uno lungo, invece (questo è l'approccio usato spesso in Clojure e Haskell).

Sono fermamente convinto che gli aspetti funzionali possono essere molto utili in JavaScript, ma in ultima analisi, si dovrebbe usare qualunque rende il codice più leggibile e ciò che funziona per voi.

Altri suggerimenti

Dovete capire che la programmazione funzionale e programmazione orientata agli oggetti sono un po 'antitetici fra loro. Non è possibile essere entrambi puramente funzionale e puramente orientato agli oggetti.

funzionale programmazione è tutto calcoli apolidi. programmazione orientata agli oggetti è tutto transizioni di stato. (Paraphasing questo . Speriamo non troppo male)

JavaScript è più orientato agli oggetti di quello che è funzionale. Il che significa che se si vuole programmare in uno stile puramente funzionale, si deve rinunciare a gran parte del linguaggio. Specificamente tutte le parti oggetto oriente.

Se si è disposti a essere più pragmatico a questo proposito, ci sono alcune ispirazioni dal mondo puramente funzionale che si potrebbe usare.

Io cerco di rispettare le seguenti regole:

Le funzioni che svolgono calcoli non dovrebbe stato di alter. E le funzioni che lo stato alter non dovrebbero eseguire calcoli. Inoltre, le funzioni che lo stato alter dovrebbero alterare il meno Stato possibile. L'obiettivo è quello di avere un sacco di piccoli funzioni che fare solo una cosa. Quindi, se avete bisogno di fare qualcosa di grande, la composizione di un gruppo di piccole funzioni per fare quello che ti serve.

Ci sono una serie di benefici per essere acquisita dal seguire queste regole:

  1. Facilità di riutilizzo. La funzione di un più lungo e complesso, tanto più specializzata è anche, e quindi la meno probabile è che può essere riutilizzato. L'implicazione inversa è che le funzioni più brevi tendono a più generico e quindi più facile da riutilizzare.

  2. L'affidabilità di codice. E 'più facile ragionare su correttezza del codice, se è meno complesso.

  3. E 'più facile per funzioni di test quando lo fanno solo una cosa. In questo modo ci sono meno casi speciali a prova.

Aggiornamento:

Incorporated suggerimento da commentare.

Aggiornamento 2:

aggiunto alcuni link utili.

Credo che, http://documentcloud.github.com/underscore/ dovrebbe essere bello adatta per quello che ti serve - fornisce la maggior parte delle funzioni importanti di ordine superiore per la programmazione funzionale e non lo fa ha funzioni lato client per la manipolazione del DOM, che non è necessario per il lato server. Anche se non ho esperienza con esso.

Come nota laterale: IMHO caratteristica primaria di programmazione funzionale è referenziale trasparenza di una funzione - risultato della funzione dipende solo suoi parametri - funzione non dipende modifiche su altri oggetti e non introduce alcun cambiamento tranne il suo valore risultante. Lo rende facile ragionare su correttezza del programma e di grande valore per l'attuazione del prevedibile multi-threading (se del caso). Anche se JavaScript non è la lingua scommessa per FP - Mi aspetto che le strutture di dati immutabili ad essere molto costoso prestazioni-saggio usare

.

Quindi, 2 cose da sottolineare,

  1. Nel vostro primo esempio la variabile non sarebbe perde nella zona globale ed è il modo in cui dovrebbe essere fatto, cercare di non usare mai le variabili senza dichiarare di loro cioè test = 'data' causerebbe i dati di infiltrarsi nella zona globale.

  2. Il secondo esempio è corretto così, bar1 e bar2 sarebbero dichiarati solo l'oggetto Foo.

cose da tenere a mente cercare di non uso eccessivo prototipazione in quanto si applica a tutti gli oggetti che si crea, questo potrebbe essere estremamente intensivo di memoria a seconda di come complesso gli oggetti sono.

Se siete alla ricerca di un framework di sviluppo app, dare un'occhiata alla ExtJs . Personalmente penso che si adatterebbe perfettamente nel modello che si sta tentando di sviluppare contro. Basta tenere a mente come il loro modello di licenza funziona prima di essere pesantemente investito in essa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top