Recentemente ho sentito parlare molto dell'uso di linguaggi funzionali come Haskell. Quali sono alcune delle grandi differenze, vantaggi e svantaggi della programmazione funzionale rispetto alla programmazione orientata agli oggetti?
Recentemente ho sentito parlare molto dell'uso di linguaggi funzionali come Haskell. Quali sono alcune delle grandi differenze, vantaggi e svantaggi della programmazione funzionale rispetto alla programmazione orientata agli oggetti?
Risposte:
Direi che è più programmazione funzionale vs programmazione imperativa .
La differenza principale è che la programmazione imperativa riguarda il flusso di controllo mentre la programmazione funzionale riguarda il flusso di dati . Un altro modo di dire è che la programmazione funzionale utilizza solo espressioni mentre nella programmazione imperativa vengono utilizzate sia espressioni che dichiarazioni .
Ad esempio, nella programmazione imperativa variabili e cicli sono comuni durante la gestione dello stato, mentre nella programmazione funzionale lo stato viene gestito tramite il passaggio di parametri, evitando effetti collaterali e assegnazioni.
Pseudo-codice imperativo per una funzione per calcolare la somma di un elenco (la somma viene mantenuta in una variabile):
int sumList(List<int> list) {
int sum = 0;
for(int n = 0; n < list.size(); n++) {
sum = sum + list.get(n);
}
return sum;
}
Pseudo-codice funzionale per la stessa funzione (la somma viene passata come parametro):
fun sumList([], sum) = sum
| sumList(v::lst, sum) = sumList(lst, v+sum)
Consiglio una presentazione Taming Effects with Functional Programming di Simon Peyton-Jones per una buona introduzione ai concetti funzionali.
La programmazione funzionale si basa su un modello dichiarativo e ha le sue radici dal calcolo lambda. Offre molti grandi concetti che possono essere presi in prestito da linguaggi più imperativi come C ++ e C #.
Alcuni esempi includono trasparenza referenziale, funzioni lambda, funzioni di prima classe, valutazione pigra e desiderosa e immutabilità.
Se non altro, l'apprendimento della programmazione funzionale è utile per i concetti che contiene. Cambierà il modo di programmare e pensare alla programmazione. E immagino che in futuro la programmazione funzionale sarà importante tanto quanto lo è stata la programmazione orientata agli oggetti.
Per iniziare puoi scegliere di usare un linguaggio funzionale puro come Haskell, oppure puoi usarne uno ibrido come F # .
La maggior parte delle buone università coprirà la programmazione funzionale e se vai a scuola ti consiglio vivamente di seguire quel corso.
Quali sono alcune delle grandi differenze, vantaggi e svantaggi della programmazione funzionale rispetto alla programmazione orientata agli oggetti?
La programmazione orientata agli oggetti è buona perché ti consente di modellare il tuo problema complesso in gerarchie in modo da poterlo semplificare. Ma diventa molto difficile quando inizi a considerare la programmazione multi-thread mentre usi oggetti mutabili. In questi casi è necessario utilizzare un uso intenso di oggetti di sincronizzazione ed è quasi impossibile perfezionare un'applicazione di grandi dimensioni.
È qui che entra in gioco la programmazione funzionale. A causa di cose come l'immutabilità, la programmazione funzionale semplifica davvero i programmi multi-thread. Rende quasi banalmente semplice parallelizzare qualcosa quando sai che dato l'input X a una funzione emetterà sempre Y. Inoltre sai che una variabile (o valore nella programmazione funzionale) non può cambiare a metà uso da un altro thread.
(Questa risposta è adattata da una risposta a una domanda chiusa su StackOverflow .)
Una delle grandi differenze tra la programmazione funzionale e la programmazione orientata agli oggetti è che ognuna è migliore in un diverso tipo di evoluzione del software:
I linguaggi orientati agli oggetti sono utili quando hai un set fisso di operazioni sulle cose e man mano che il tuo codice si evolve, aggiungi principalmente nuove cose. Ciò può essere ottenuto aggiungendo nuove classi che implementano metodi esistenti e le classi esistenti vengono lasciate sole.
I linguaggi funzionali sono buoni quando hai un set fisso di cose e man mano che il tuo codice si evolve, aggiungi principalmente nuove operazioni su cose esistenti. Ciò può essere ottenuto aggiungendo nuove funzioni che calcolano con tipi di dati esistenti e le funzioni esistenti vengono lasciate sole.
Quando l'evoluzione va nella direzione sbagliata, hai problemi:
L'aggiunta di una nuova operazione a un programma orientato agli oggetti potrebbe richiedere la modifica di molte definizioni di classe per aggiungere un nuovo metodo.
L'aggiunta di un nuovo tipo di cose a un programma funzionale potrebbe richiedere la modifica di molte definizioni di funzioni per aggiungere un nuovo caso.
Questo problema è noto da molti anni; nel 1998, Phil Wadler lo ha definito il "problema dell'espressione" . Sebbene alcuni ricercatori ritengano che il problema dell'espressione possa essere affrontato con caratteristiche linguistiche come i mixin, una soluzione ampiamente accettata deve ancora raggiungere il mainstream.
Non c'è vero contro. Possono essere perfettamente complementari. Esistono lingue FP che supportano OOP. Ma le comunità differiscono nel modo in cui gestiscono la modularità.
Gli utenti dei linguaggi FP tendono a raggiungere la modularità attraverso leggi matematiche. E preferisce le prove per dimostrare la conformità con le loro leggi.
In OOP imperativo gli utenti tendono a catturare il comportamento dell'oggetto nei casi di test, che possono essere rieseguiti se l'oggetto è cambiato e ottenere così la modularità.
È solo un piccolo aspetto, ma penso che valga la pena menzionarlo.
Un'analogia:
Ti viene consegnata una domanda di lavoro. Inserisci il tuo nome, le informazioni di contatto e la cronologia dei lavori. Quando hai finito non hai più un'applicazione vuota.
Ora immagina invece che prima di scriverlo lo ricopri con un foglio di cellophane trasparente. Scrivi il tuo nome. Aggiungi un altro foglio di cellophane. Scrivi le tue informazioni di contatto. Più cellophane. Scrivi la tua storia lavorativa. Quando hai finito hai ancora l'applicazione vuota intatta. Hai anche tre fogli di cellophane ciascuno dopo aver catturato l'effetto di un singolo, discreto cambiamento.
Il primo (OOP) abbraccia l'idea di cambiare le cose sul posto mentre il secondo (FP) la evita. Entrambi sono paradigmi di gestione dello stato. Entrambi possono, usando strategie diverse, catturare l'effetto del completamento di una domanda di lavoro. OOP modifica direttamente lo strumento di partenza, mentre FP sovrappone ciò che è accaduto prima per influenzare l'aspetto del cambiamento .