Imagina que queremos aplicar una serie de funciones a xsi y solo si xno es nulo:
if (x !== null) x = a(x);
if (x !== null) x = b(x);
if (x !== null) x = c(x);
Ahora digamos que necesitamos hacer lo mismo para y:
if (y !== null) y = a(y);
if (y !== null) y = b(y);
if (y !== null) y = c(y);
Y lo mismo para z:
if (z !== null) z = a(z);
if (z !== null) z = b(z);
if (z !== null) z = c(z);
Como puede ver, sin una abstracción adecuada, terminaremos duplicando el código una y otra vez. Tal abstracción ya existe: la mónada Quizás .
La mónada Maybe tiene tanto un valor como un contexto computacional:
- La mónada mantiene el valor seguro y le aplica funciones.
- El contexto computacional es una verificación nula antes de aplicar una función.
Una implementación ingenua se vería así:
⚠️ ¡Esta implementación es solo para fines ilustrativos! No es así como debería hacerse y está mal en muchos niveles. Sin embargo, esto debería darle una mejor idea de lo que estoy hablando.
Como puede ver, nada se puede romper:
- Aplicamos una serie de funciones a nuestro valor
- Si en algún momento, el valor se vuelve nulo (o indefinido), ya no aplicamos ninguna función.
const abc = obj =>
Maybe
.of(obj)
.map(o => o.a)
.map(o => o.b)
.map(o => o.c)
.value;
const values = [
{},
{a: {}},
{a: {b: {}}},
{a: {b: {c: 42}}}
];
console.log(
values.map(abc)
);
<script>
function Maybe(x) {
this.value = x; //-> container for our value
}
Maybe.of = x => new Maybe(x);
Maybe.prototype.map = function (fn) {
if (this.value == null) { //-> computational context
return this;
}
return Maybe.of(fn(this.value));
};
</script>
Apéndice 1
No puedo explicar qué son las mónadas ya que este no es el propósito de esta publicación y hay gente mejor que yo en esto. Sin embargo, como dijo Eric Elliot en la publicación de su blog, JavaScript Monads Made Simple :
Independientemente de su nivel de habilidad o comprensión de la teoría de categorías, el uso de mónadas facilita el trabajo con su código. No aprovechar las mónadas puede dificultar el trabajo con su código (por ejemplo, infierno de devolución de llamada, ramas condicionales anidadas, más verbosidad).
Apéndice 2
Así es como resolvería su problema usando la mónada Quizás demonetjs
const prop = key => obj => Maybe.fromNull(obj[key]);
const abc = obj =>
Maybe
.fromNull(obj)
.flatMap(prop('a'))
.flatMap(prop('b'))
.flatMap(prop('c'))
.orSome('🌯')
const values = [
{},
{a: {}},
{a: {b: {}}},
{a: {b: {c: 42}}}
];
console.log(
values.map(abc)
);
<script src="https://www.unpkg.com/monet@0.9.0/dist/monet.js"></script>
<script>const {Maybe} = Monet;</script>
try..catchdeclaración. Dicho esto, una matriz que contiene elementos tremendamente heterogéneos me parece un problema de diseño.