A beginner friendly intro to functional programming
Functional programming is a highly valued approach to writing code, and it’s popularity is continuously increasing in applicazioni software commerciali. La programmazione funzionale è un paradigma di scrittura del codice ed è eloquentemente inserita nell’introduzione di questo articolo di Wikipedia:
” -uno stile di costruzione della struttura e degli elementi dei programmi per computer — che tratta il calcolo come la valutazione di funzioni matematiche ed evita i dati mutevoli e mutevoli. È un paradigma di programmazione dichiarativa, il che significa che la programmazione viene eseguita con espressioni o dichiarazioni anziché dichiarazioni.”
Entreremo in cosa significa esattamente molto presto, ma prima, togliamo i fondamenti di mezzo fornendo un certo contesto. Questo articolo ha lo scopo di introdurre i concetti fondamentali della programmazione funzionale e, alla fine, avremmo stabilito una comprensione di base del motivo per cui avremmo scelto di applicarlo nei nostri stili di codifica, in che modo si riferisce a JavaScript e alcuni modelli di base che è possibile iniziare a implementare nel codice. Essere alla ricerca di un secondo articolo che si baserà su questo e scavare ancora più a fondo le idee discusse qui.
Le radici della programmazione funzionale si trovano nel Lambda calculus, che era un sistema sviluppato negli anni ‘ 30 per esprimere il calcolo usando funzioni simili a quelle che vedremo molto presto. Per un bel po’, i concetti e i linguaggi di programmazione funzionale sono stati ampiamente discussi nel mondo accademico e nei contesti accademici e alla fine sono sfociati nello sviluppo di software commerciale. Ciò che rende un linguaggio di programmazione funzionale o meno è la sua capacità di facilitare il paradigma di programmazione funzionale, linguaggi come questi sono Ruby, Python, Julia e JavaScript, l’ultimo dei quali ha proprietà di paradigmi imperativi, orientati agli oggetti e funzionali.
Diamo un’occhiata a un esempio di utilizzo di un imperativo e quindi di un approccio funzionale al completamento di una singola attività.
Imperativo:
const arr = function getOdds(arr){
let odds = ; for(let i = 0; i < arr.length + 1; i++){
if ( i % 2 !== 0 ){
odds.push( i )
};
};
return odds
};console.log(getOdds(arr))
// logs
Funzionale:
function getOdds2(arr){
return arr.filter(num => num % 2 !== 0)
}console.log(getOdds2(arr))
// logs // this can be even shorter
const getOdds3 = arr => arr.filter(num => num % 2 !== 0)console.log(getOdds3(arr))
// logs
A parte gli ovvi miglioramenti che l’approccio funzionale rende, come il codice più breve, salvandoci un paio di tasti, e il fatto che è molto più facile da capire a colpo d’occhio, è anche elegante, il che si traduce in un codice più pulito, semplifica il debug, il test e la manutenzione.
Scomponiamo un po ‘ questo, in modo da poter raggiungere una chiara comprensione delle differenze tra i due approcci e definire cos’è la programmazione funzionale.
Nel primo approccio stiamo descrivendo imperativamente ogni evento che deve aver luogo per poter ottenere il compito di filtrare i numeri dispari da un array. Alimentiamo una funzione un array, all’interno della funzione creiamo un array vuoto che useremo per memorizzare i numeri dispari. Gli diciamo di eseguire il loop sull’array, quindi dichiariamo un condizionale, se l’indice corrente è un numero dispari, lo spingiamo a quello vuoto. Il ciclo for non include l’ultimo numero nell’array, include solo i numeri che lo precedono, quindi se il nostro ultimo numero è dispari, non sarà incluso. Quindi aggiungiamo + 1 quando definiamo la quantità di iterazioni che il nostro ciclo deve fare.
Nel secondo approccio, definiamo semplicemente il risultato che vogliamo vedere usando un metodo chiamato filter e permettiamo alla macchina di occuparsi di tutti i passaggi intermedi. Questo è un approccio più dichiarativo. Dichiariamo quale deve essere il risultato finale, e noi il resto è gestito per noi.
Ora possiamo vedere ciò che la definizione sopra menzionata si sforza di esprimere. Un modo di programmare, usando dichiarazioni ed espressioni, piuttosto che dichiarazioni. Questa definizione raschia solo la superficie della programmazione funzionale e continueremo a basarci sulla nostra definizione man mano che la nostra comprensione cresce.
Alcune differenze tra approcci iterativi e funzionali.
- Stilisticamente, definiamo un problema e i cambiamenti che vorremmo vedere, invece di spiegarlo passo dopo passo.
- Non abbiamo bisogno di gestire lo stato nelle nostre funzioni come sopra dove abbiamo gestito lo stato del nostro array vuoto.
- Non dobbiamo preoccuparci tanto dell’ordine di esecuzione.
- Usiamo meno loop, condizioni e usiamo più metodi integrati, funzioni riutilizzabili e ricorsioni.
Utilizzando questo approccio, alla fine scriviamo codice più pulito che, come menzionato sopra, ci aiuta nel debug e nella manutenzione. Mantiene le cose modulari e sezioni del nostro codice sono suddivise in pezzi più piccoli che possiamo testare con facilità. Possiamo riutilizzare parti del nostro codice usando le funzioni di supporto e, infine, è un approccio matematico più efficiente per scrivere codice.
I pilastri: Il nostro toolkit di codifica per la scrittura di codice funzionale
I seguenti sono alcuni aspetti importanti per la scrittura di codice funzionale di alta qualità. Vedendo che questa è una panoramica, non ci immergeremo troppo in ciascuno, ma definiremo solo alcune caratteristiche chiave e un esempio di ciascuno.
Funzioni pure:
Le funzioni pure restituiscono un valore basato esclusivamente su ciò che è stato passato in esso. L’idea alla base è che sarà una funzione pura se restituisce sempre lo stesso risultato se vengono passati gli stessi valori e non modifica i valori al di fuori dell’ambito ts, il che lo rende indipendente da qualsiasi stato nel sistema. Pertanto, una funzione pura non può mai mutare i dati, non produrre effetti collaterali e può essere facilmente riutilizzata. Un esempio di una funzione non pura sarà una funzione che effettua una chiamata API o restituisce un risultato imprevedibile.
Semplice funzione impura:
var tip = 0;function calculateTip( mealTotal ) {
tip = 0.15 * mealTotal;
}calculateTip( 150 )
console.log(tip)
Semplice funzione pura:
function isPure(x,y) {
return x * y
}console.log(isPure(3,5));
La funzione pura restituirà il risultato esatto ogni volta e non muterà alcun dato al di fuori di esso. La cosa importante a cui prestare attenzione è che una funzione pura deve stare lontana dal mutare i dati di sorta, quindi fai attenzione quando selezioni quali metodi usare all’interno delle tue funzioni pure. Ad esempio, se si desidera unire due array all’interno della funzione, come si farebbe in genere in un riduttore React, evitare di utilizzare l’Array.prototipo.metodo push (). Invece vorresti usare Array.prototipo.concat (), che preserverà lo stato dei vecchi array e ne restituirà uno nuovo per l’uso.
Funzioni di ordine superiore:
In Javascript, le funzioni sono trattate come oggetti, quindi possiamo passare le funzioni come faremmo con qualsiasi altro valore. Una funzione di ordine superiore è semplicemente una funzione che opera su altre funzioni. Possono prendere una funzione come input o restituirne una come output. Vedremo un semplice esempio nella seguente dimostrazione.
Funzioni anonime:
Le funzioni anonime sono molto utili quando abbiamo bisogno di definire una logica ad hoc di cui abbiamo bisogno. Come suggerisce il nome, una funzione anonima in nameless, e per lo più trovato come argomento di una funzione in sostituzione di una funzione con nome, una funzione assegnata a una variabile, o restituito come una funzione in una funzione di ordine superiore. Le sue radici si trovano pesantemente nel calcolo Lambda ed è molto importante per tutti i linguaggi di programmazione funzionali.
Funzione anonima assegnata a una variabile. Facile da passare in giro e richiamare quando necessario.
const myVar = function(){console.log(‘Anonymous function here!’)}myVar()
funzione Anonima come argomento
setInterval(function(){console.log(new Date().getTime())}, 1000);
funzioni Anonime all’interno di un ordine superiore funzione
function mealCall(meal){
return function(message){
return console.log(message + " " + meal + ‘!!’)
}
}const announceDinner = mealCall(‘dinner’)
const announceLunch = mealCall(‘breakfast’)announceDinner(‘hey!, come and get your’)
announceLunch(‘Rise and shine! time for’)
la Ricorsione
la Ricorsione è un noto funzionale tecnica di programmazione. Una funzione ricorsiva è semplicemente una funzione che si chiama e quindi agisce come un ciclo che esegue lo stesso codice più volte. Viene fornito con un avvertimento però, bisogna stare attenti a evitare infinite ricorsioni. Pertanto è necessario un caso base, per dirgli quando fermarsi. Funzioni o algoritmi ricorsivi possono essere implementati usando ricorsione e loop, ma è meglio usare la ricorsione. Di seguito è riportato l’algoritmo ben noto per fattorizzare un numero sia usando la ricorsione che un ciclo.
Funzione ricorsiva
function factorialize(num){
if (num === 0 || num === 1){return 1;}
return (num * factorialize(num — 1));
}var result = factorialize(14);console.log(result);
Ricorsione utilizzando un ciclo
function factorialize(num) {
if (num === 0 || num === 1){
return 1;
}
for (var i = num-1; i >= 1; i-- ) {
num *= i;
}
return num;
}
console.log(factorialize(6));
Abbiamo coperto alcuni degli ingredienti essenziali per scrivere codice funzionale. Non è possibile scrivere sempre codice funzionale in un’applicazione, ma i vantaggi sono grandi se usati il più possibile. Framework come Angular e React sono fortemente influenzati dalla programmazione funzionale e librerie come Redux e Lodash ci consentono di utilizzarne i vantaggi, quindi c’è sicuramente un grande vantaggio per iniziare a pensare in modo FP.
Risorse per saperne di più? Qui ci sono alcuni grandi articoli e risorse per un ulteriore apprendimento.
- Perché imparare la programmazione funzionale in JavaScript? da Eric Elliot
- Eloquente JavaScript di Marijn Haverbeke
- Così si vuole essere un Funzionale Programmatore da Carlo Scalfani
spero davvero che questo è stato utile e nel prossimo articolo ci immergeremo un po ‘ di più e decomprimere ancora più interessanti e utili strumenti come i metodi JavaScript, parziale applicazione, accattivarsi, argomento di associazione e di più.
Sentitevi liberi di battere le mani, condividere, criticare o condividere qualsiasi pensiero sul tema!