Buscar..
Observaciones
¿Qué es la programación funcional?
Programación funcional o PF es un paradigma de programación que se basa en dos conceptos principales: inmutabilidad y apatridia . El objetivo detrás de la PF es hacer que su código sea más legible, reutilizable y portátil.
¿Qué es JavaScript funcional?
Ha habido un debate para llamar a JavaScript como un lenguaje funcional o no. Sin embargo, absolutamente podemos usar JavaScript como funcional debido a su naturaleza:
- Tiene funciones puras
- Tiene funciones de primera clase
- Tiene una función de orden superior
- Es compatible con la inmutabilidad.
- Tiene cierres
- Recursión y lista de métodos de transformación (matrices) como map, reduce, filter..etc
Los ejemplos deben cubrir cada concepto en detalle, y los enlaces que se proporcionan aquí son solo para referencia, y deben eliminarse una vez que se ilustra el concepto.
Aceptando funciones como argumentos
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]
Como puede ver, nuestra función de transform
acepta dos parámetros, una función y una colección. A continuación, iterará la colección e insertará los valores en el resultado, llamando a fn
en cada uno de ellos.
¿Luce familiar? ¡Esto es muy similar a cómo Array.prototype.map()
funciona!
console.log([1, 2, 3, 4].map(x => x * 2)); // [2, 4, 6, 8]
Funciones de orden superior
En general, las funciones que operan en otras funciones, ya sea tomándolas como argumentos o devolviéndolas (o ambas), se llaman funciones de orden superior.
Una función de orden superior es una función que puede tomar otra función como argumento. Está utilizando funciones de orden superior al pasar devoluciones de llamada.
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 función de orden superior es también una función que devuelve otra función como su resultado.
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()();
Mada de identidad
Este es un ejemplo de una implementación de la mónada de identidad en JavaScript y podría servir como punto de partida para crear otras mónadas.
Basado en la conferencia de Douglas Crockford sobre mónadas y gónadas.
El uso de este enfoque reutilizará sus funciones debido a la flexibilidad que proporciona esta mónada y las pesadillas de composición:
f(g(h(i(j(k(value), j1), i2), h1, h2), g1, g2), f1, f2)
legible, agradable y limpio:
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;
};
Funciona con valores primitivos.
var value = 'foo',
f = x => x + ' changed',
g = x => x + ' again';
identityMonad(value)
.apply(f)
.apply(g)
.bind(alert); // Alerts 'foo changed again'
Y tambien con objetos.
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'
Probemos todo:
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
Funciones puras
Un principio básico de la programación funcional es que evita cambiar el estado de la aplicación (sin estado) y las variables fuera de su alcance (inmutabilidad).
Las funciones puras son funciones que:
- con una entrada dada, siempre devuelve la misma salida
- No confían en ninguna variable fuera de su alcance.
- no modifican el estado de la aplicación ( sin efectos secundarios )
Echemos un vistazo a algunos ejemplos:
Las funciones puras no deben cambiar ninguna variable fuera de su alcance.
Función 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 función cambió el valor obj.a
que está fuera de su alcance.
Función 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 función no cambió los valores del objeto obj
Las funciones puras no deben depender de variables fuera de su alcance.
Función 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
Esta función impura se basa en la variable a
que se define fuera de su alcance. Entonces, si se modifica a, el resultado de la función de impure
será diferente.
Función 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
La pure
's resultado de la función no depende de ninguna variable fuera su alcance.