Zoeken…
Opmerkingen
Wat is functioneel programmeren?
Functioneel programmeren of FP is een programmeerparadigma dat is gebaseerd op twee hoofdconcepten onveranderbaarheid en staatloosheid . Het doel achter FP is om uw code leesbaarder, herbruikbaar en draagbaar te maken.
Wat is functionele JavaScript
Er is een debat gaande om JavaScript een functionele taal te noemen of niet, maar we kunnen JavaScript absoluut als functioneel gebruiken vanwege zijn aard:
- Heeft pure functies
- Heeft eersteklas functies
- Heeft hogere orderfunctie
- Het ondersteunt onveranderlijkheid
- Heeft sluitingen
- Recursion en List Transforation Methods (Arrays) zoals map, reduceren, filter..etc
De voorbeelden moeten elk concept in detail behandelen, en de links die hier worden gegeven, zijn alleen voor referentie en moeten worden verwijderd zodra het concept is geïllustreerd.
Functies accepteren als argumenten
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]
Zoals u ziet, accepteert onze transform
twee parameters, een functie en een verzameling. Het zal dan de verzameling herhalen en waarden naar het resultaat pushen, waarbij fn
op elk van hen wordt fn
.
Komt me bekend voor? Dit lijkt erg op hoe Array.prototype.map()
werkt!
console.log([1, 2, 3, 4].map(x => x * 2)); // [2, 4, 6, 8]
Hogere-orde functies
Over het algemeen worden functies die op andere functies werken, door ze als argumenten te nemen of door ze terug te geven (of beide), functies van een hogere orde genoemd.
Een hogere orde functie is een functie die een andere functie als argument kan nemen. U gebruikt functies van een hogere orde wanneer u callbacks doorgeeft.
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);
Een hogere orde functie is ook een functie die als resultaat een andere functie retourneert.
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()();
Identiteit Monad
Dit is een voorbeeld van een implementatie van de identiteitsmonade in JavaScript en kan als startpunt dienen om andere monaden te maken.
Gebaseerd op de conferentie van Douglas Crockford over monaden en geslachtsklieren
Het gebruik van deze benadering zal het hergebruiken van uw functies gemakkelijker maken vanwege de flexibiliteit die deze monade biedt en nachtmerries over de compositie:
f(g(h(i(j(k(value), j1), i2), h1, h2), g1, g2), f1, f2)
leesbaar, mooi en schoon:
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;
};
Het werkt met primitieve waarden
var value = 'foo',
f = x => x + ' changed',
g = x => x + ' again';
identityMonad(value)
.apply(f)
.apply(g)
.bind(alert); // Alerts 'foo changed again'
En ook met objecten
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'
Laten we alles proberen:
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 functies
Een basisprincipe van functioneel programmeren is dat het voorkomt dat de applicatiestatus (staatloosheid) en variabelen buiten zijn bereik (onveranderlijkheid) worden gewijzigd .
Pure functies zijn functies die:
- retourneer bij een gegeven invoer altijd dezelfde uitvoer
- ze vertrouwen niet op een variabele buiten hun bereik
- ze veranderen de status van de applicatie niet ( geen bijwerkingen )
Laten we een paar voorbeelden bekijken:
Pure functies mogen geen variabele buiten hun bereik veranderen
Onzuivere functie
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
De functie heeft de obj.a
waarde gewijzigd die buiten het bereik valt.
Pure functie
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
De functie heeft de object obj
waarden niet gewijzigd
Pure functies mogen niet afhankelijk zijn van variabelen die buiten hun bereik vallen
Onzuivere functie
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
Deze onzuivere functie is afhankelijk van variabele a
die buiten zijn bereik wordt gedefinieerd. Dus als a wordt gewijzigd, zal het functieresultaat van impure
anders zijn.
Pure functie
let pure = (input) => {
let a = 1;
// Multiply with variable inside function scope
let output = input * a;
return output;
}
console.log(pure(2)) // Logs 2
Het functieresultaat van de pure
is niet afhankelijk van een variabele buiten zijn bereik.