Ricerca…
Osservazioni
Che cos'è la programmazione funzionale?
La programmazione funzionale o FP è un paradigma di programmazione basato su due concetti principali di immutabilità e apolidia . L'obiettivo di FP è rendere il codice più leggibile, riutilizzabile e portatile.
Cos'è il JavaScript funzionale
C'è stato un dibattito per chiamare JavaScript un linguaggio funzionale o no. Tuttavia, possiamo assolutamente usare JavaScript come funzionale per la sua natura:
- Ha pure funzioni
- Ha funzioni di prima classe
- Ha una funzione di ordine superiore
- Supporta l' immutabilità
- Ha le chiusure
- Recursion e List Transforation Methods (Arrays) come map, reduce, filter..etc
Gli esempi dovrebbero riguardare ogni concetto in dettaglio, ei collegamenti forniti qui sono solo per riferimento e dovrebbero essere rimossi una volta che il concetto è illustrato.
Accettare le funzioni come argomenti
function transform(fn, arr) {
let result = [];
for (let el of arr) {
result.push(fn(el)); // We push the result of the transformed item to result
}
return result;
}
console.log(transform(x => x * 2, [1,2,3,4])); // [2, 4, 6, 8]
Come puoi vedere, la nostra funzione di transform
accetta due parametri, una funzione e una collezione. Quindi eseguirà l'iterazione della raccolta e sposterà i valori sul risultato, chiamando fn
su ciascuno di essi.
Sembra familiare? Questo è molto simile a come funziona Array.prototype.map()
!
console.log([1, 2, 3, 4].map(x => x * 2)); // [2, 4, 6, 8]
Funzioni di ordine superiore
In generale, le funzioni che operano su altre funzioni, assumendole come argomenti o restituendole (o entrambe), sono chiamate funzioni di ordine superiore.
Una funzione di ordine superiore è una funzione che può assumere un'altra funzione come argomento. Stai utilizzando le funzioni di ordine superiore durante il passaggio di callback.
function iAmCallbackFunction() {
console.log("callback has been invoked");
}
function iAmJustFunction(callbackFn) {
// do some stuff ...
// invoke the callback function.
callbackFn();
}
// invoke your higher-order function with a callback function.
iAmJustFunction(iAmCallbackFunction);
Una funzione di ordine superiore è anche una funzione che restituisce un'altra funzione come risultato.
function iAmJustFunction() {
// do some stuff ...
// return a function.
return function iAmReturnedFunction() {
console.log("returned function has been invoked");
}
}
// invoke your higher-order function and its returned function.
iAmJustFunction()();
Identity Monad
Questo è un esempio di implementazione della monade dell'identità in JavaScript e potrebbe servire come punto di partenza per creare altre monadi.
Basato sulla conferenza di Douglas Crockford su monadi e gonadi
Utilizzando questo approccio riutilizzare le tue funzioni sarà più facile grazie alla flessibilità offerta da questa monade e agli incubi della composizione:
f(g(h(i(j(k(value), j1), i2), h1, h2), g1, g2), f1, f2)
leggibile, bello e pulito:
identityMonad(value)
.bind(k)
.bind(j, j1, j2)
.bind(i, i2)
.bind(h, h1, h2)
.bind(g, g1, g2)
.bind(f, f1, f2);
function identityMonad(value) {
var monad = Object.create(null);
// func should return a monad
monad.bind = function (func, ...args) {
return func(value, ...args);
};
// whatever func does, we get our monad back
monad.call = function (func, ...args) {
func(value, ...args);
return identityMonad(value);
};
// func doesn't have to know anything about monads
monad.apply = function (func, ...args) {
return identityMonad(func(value, ...args));
};
// Get the value wrapped in this monad
monad.value = function () {
return value;
};
return monad;
};
Funziona con valori primitivi
var value = 'foo',
f = x => x + ' changed',
g = x => x + ' again';
identityMonad(value)
.apply(f)
.apply(g)
.bind(alert); // Alerts 'foo changed again'
E anche con gli oggetti
var value = { foo: 'foo' },
f = x => identityMonad(Object.assign(x, { foo: 'bar' })),
g = x => Object.assign(x, { bar: 'foo' }),
h = x => console.log('foo: ' + x.foo + ', bar: ' + x.bar);
identityMonad(value)
.bind(f)
.apply(g)
.bind(h); // Logs 'foo: bar, bar: foo'
Proviamo tutto:
var add = (x, ...args) => x + args.reduce((r, n) => r + n, 0),
multiply = (x, ...args) => x * args.reduce((r, n) => r * n, 1),
divideMonad = (x, ...args) => identityMonad(x / multiply(...args)),
log = x => console.log(x),
substract = (x, ...args) => x - add(...args);
identityMonad(100)
.apply(add, 10, 29, 13)
.apply(multiply, 2)
.bind(divideMonad, 2)
.apply(substract, 67, 34)
.apply(multiply, 1239)
.bind(divideMonad, 20, 54, 2)
.apply(Math.round)
.call(log); // Logs 29
Pure funzioni
Un principio di base della programmazione funzionale è che evita di modificare lo stato dell'applicazione (apolidia) e le variabili al di fuori del suo ambito (immutabilità).
Le funzioni pure sono funzioni che:
- con un dato input, restituisce sempre lo stesso output
- non si basano su alcuna variabile al di fuori del loro scopo
- non modificano lo stato dell'applicazione ( senza effetti collaterali )
Diamo un'occhiata ad alcuni esempi:
Le funzioni pure non devono modificare alcuna variabile al di fuori del loro ambito
Funzione impura
let obj = { a: 0 }
const impure = (input) => {
// Modifies input.a
input.a = input.a + 1;
return input.a;
}
let b = impure(obj)
console.log(obj) // Logs { "a": 1 }
console.log(b) // Logs 1
La funzione ha cambiato il valore obj.a
al di fuori del suo ambito.
Funzione pura
let obj = { a: 0 }
const pure = (input) => {
// Does not modify obj
let output = input.a + 1;
return output;
}
let b = pure(obj)
console.log(obj) // Logs { "a": 0 }
console.log(b) // Logs 1
La funzione non ha modificato i valori obj
obiettivo
Le funzioni pure non devono basarsi su variabili al di fuori del loro ambito
Funzione impura
let a = 1;
let impure = (input) => {
// Multiply with variable outside function scope
let output = input * a;
return output;
}
console.log(impure(2)) // Logs 2
a++; // a becomes equal to 2
console.log(impure(2)) // Logs 4
Questa funzione impura si basa sulla variabile a
che è definita al di fuori del suo ambito. Quindi, se a viene modificato, il risultato della funzione impure
sarà diverso.
Funzione pura
let pure = (input) => {
let a = 1;
// Multiply with variable inside function scope
let output = input * a;
return output;
}
console.log(pure(2)) // Logs 2
Il risultato della funzione pure
non si basa su alcuna variabile al di fuori del suo ambito.