introduzione
La programmazione funzionale è un paradigma di programmazione in cui cerchiamo di legare tutto in puro stile di funzioni matematiche. È uno stile di programmazione di tipo dichiarativo. Il suo obiettivo principale è cosa risolvere in contrasto con uno stile imperativo in cui l'obiettivo principale è come risolvere. Utilizza espressioni invece di istruzioni. Un'espressione viene valutata per produrre un valore mentre un'istruzione viene eseguita per assegnare variabili. Tali funzioni presentano alcune caratteristiche speciali discusse di seguito.
La Programmazione Funzionale si basa sul Lambda Calcolo:
Il lambda calcolo è un framework sviluppato da Alonzo Church per studiare calcoli con funzioni. Può essere definito il linguaggio di programmazione più piccolo del mondo. Fornisce la definizione di ciò che è calcolabile. Tutto ciò che può essere calcolato mediante il lambda calcolo è calcolabile. È equivalente alla macchina di Turing nella sua capacità di calcolo. Fornisce un quadro teorico per descrivere le funzioni e la loro valutazione. Costituisce la base di quasi tutti gli attuali linguaggi di programmazione funzionale.
Fatto: Alan Turing era uno studente di Alonzo Church che creò la macchina di Turing che gettò le basi dello stile di programmazione imperativa.
Linguaggi di programmazione che supportano la programmazione funzionale: Haskell, JavaScript, Python, Scala, Erlang, Lisp, ML, Clojure, OCaml, Common Lisp, Racket.
Concetti di programmazione funzionale:
- Funzioni pure
- Ricorsione Trasparenza referenziale Le funzioni sono di prima classe e possono essere di ordine superiore. Le variabili sono immutabili
Funzioni pure: Queste funzioni hanno due proprietà principali. Innanzitutto, producono sempre lo stesso output per gli stessi argomenti indipendentemente da qualsiasi altra cosa.
In secondo luogo, non hanno effetti collaterali, ovvero non modificano alcun argomento, variabile locale/globale o flusso di input/output.
La proprietà successiva è chiamata immutabilità. L’unico risultato della funzione pura è il valore che restituisce. Sono deterministici.
I programmi realizzati utilizzando la programmazione funzionale sono facili da eseguire il debug perché le funzioni pure non hanno effetti collaterali o I/O nascosti. Le funzioni pure semplificano inoltre la scrittura di applicazioni parallele/concorrenti. Quando il codice è scritto in questo stile, un compilatore intelligente può fare molte cose: può parallelizzare le istruzioni, attendere di valutare i risultati quando ne hanno bisogno e memorizzare i risultati poiché i risultati non cambiano mai finché non cambia l'input.
esempio della funzione pura:
sum(x, y) // sum is function taking x and y as arguments return x + y // sum is returning sum of x and y without changing them>
Ricorsione: Non ci sono cicli for o while nei linguaggi funzionali. L'iterazione nei linguaggi funzionali viene implementata tramite la ricorsione. Le funzioni ricorsive richiamano ripetutamente se stesse, fino a raggiungere il caso base.
esempio della funzione ricorsiva:
fib(n) if (n <= 1) return 1; else return fib(n - 1) + fib(n - 2);>
Trasparenza referenziale: Nei programmi funzionali le variabili una volta definite non cambiano il loro valore durante il programma. I programmi funzionali non hanno istruzioni di assegnazione. Se dobbiamo memorizzare qualche valore, definiamo invece nuove variabili. Ciò elimina qualsiasi possibilità di effetti collaterali perché qualsiasi variabile può essere sostituita con il suo valore effettivo in qualsiasi momento dell'esecuzione. Lo stato di qualsiasi variabile è costante in ogni istante.
Esempio:
x = x + 1 // this changes the value assigned to the variable x. // So the expression is not referentially transparent.>
Le funzioni sono di prima classe e possono essere di ordine superiore: Le funzioni di prima classe vengono trattate come variabili di prima classe. Le variabili della prima classe possono essere passate alle funzioni come parametri, possono essere restituite da funzioni o memorizzate in strutture dati. Le funzioni di ordine superiore sono le funzioni che accettano altre funzioni come argomenti e possono anche restituire funzioni.
Esempio:
show_output(f) // function show_output is declared taking argument f // which are another function f(); // calling passed function print_gfg() // declaring another function print('hello gfg'); show_output(print_gfg) // passing function in another function> Le variabili sono immutabili: Nella programmazione funzionale, non possiamo modificare una variabile dopo che è stata inizializzata. Possiamo creare nuove variabili, ma non possiamo modificare le variabili esistenti e questo aiuta davvero a mantenere lo stato durante l'esecuzione di un programma. Una volta creata una variabile e impostato il suo valore, possiamo avere piena fiducia sapendo che il valore di quella variabile non cambierà mai.
Vantaggi e svantaggi della programmazione funzionale
Vantaggi:
- Le funzioni pure sono più facili da comprendere perché non modificano nessuno stato e dipendono solo dall’input loro fornito. Qualunque sia l’output che producono è il valore di ritorno che danno. La firma della funzione fornisce tutte le informazioni su di essi, ad esempio il tipo restituito e gli argomenti.
- La capacità dei linguaggi di programmazione funzionale di trattare le funzioni come valori e di passarle alle funzioni come parametri rende il codice più leggibile e facilmente comprensibile.
- Il test e il debug sono più semplici. Poiché le funzioni pure accettano solo argomenti e producono output, non producono alcuna modifica, non accettano input né producono output nascosto. Usano valori immutabili, quindi diventa più facile verificare alcuni problemi nei programmi scritti utilizzando funzioni pure.
- Viene utilizzato per implementare la concorrenza/parallelismo perché le funzioni pure non modificano le variabili o altri dati al di fuori di esso.
- Adotta una valutazione pigra che evita valutazioni ripetute perché il valore viene valutato e memorizzato solo quando è necessario.
Svantaggi:
- A volte scrivere funzioni pure può ridurre la leggibilità del codice.
- Scrivere programmi in stile ricorsivo invece di usare i loop può essere un po' intimidatorio.
- Scrivere funzioni pure è semplice, ma combinarle con il resto dell'applicazione e con le operazioni di I/O è un compito difficile.
- I valori immutabili e la ricorsione possono portare a una diminuzione delle prestazioni.
Applicazioni:
- È utilizzato nei calcoli matematici.
- È necessario laddove è richiesta concorrenza o parallelismo.
Fatto: Whatsapp ha bisogno solo di 50 ingegneri per i suoi 900M utenti perché Erlang viene utilizzato per implementare le sue esigenze di concorrenza. Facebook utilizza Haskell nel suo sistema anti-spam.