Wyobraź sobie, że chcemy zastosować serię funkcji do xwtedy i tylko wtedy, gdy xjest różna od null:
if (x !== null) x = a(x);
if (x !== null) x = b(x);
if (x !== null) x = c(x);
Powiedzmy teraz, że musimy zrobić to samo, aby y:
if (y !== null) y = a(y);
if (y !== null) y = b(y);
if (y !== null) y = c(y);
To samo dotyczy z:
if (z !== null) z = a(z);
if (z !== null) z = b(z);
if (z !== null) z = c(z);
Jak widać bez odpowiedniej abstrakcji, w końcu będziemy ciągle dublować kod. Taka abstrakcja już istnieje: monada Może .
Może monada posiada zarówno wartość i obliczeniowej kontekst:
- Monada zapewnia bezpieczeństwo wartości i stosuje do niej funkcje.
- Kontekst obliczeniowy to sprawdzenie zerowe przed zastosowaniem funkcji.
Naiwna implementacja wyglądałaby tak:
⚠️ Ta implementacja ma charakter wyłącznie ilustracyjny! Nie należy tego robić i jest złe na wielu poziomach. Powinno to jednak dać lepsze pojęcie o tym, o czym mówię.
Jak widać, nic nie może się zepsuć:
- Do naszej wartości stosujemy szereg funkcji
- Jeśli w dowolnym momencie wartość stanie się pusta (lub niezdefiniowana), po prostu nie stosujemy już żadnej funkcji.
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>
Załącznik 1
Nie potrafię wyjaśnić, czym są monady, ponieważ nie jest to celem tego postu, a są w tym ludzie lepsi niż ja. Jednak, jak powiedział Eric Elliot w swoim poście na blogu JavaScript Monads Made Simple :
Niezależnie od Twojego poziomu umiejętności lub zrozumienia teorii kategorii, używanie monad ułatwia pracę z kodem. Niekorzystanie z monad może utrudnić pracę z kodem (np. Piekło wywołań zwrotnych, zagnieżdżone gałęzie warunkowe, więcej gadatliwości).
Załącznik 2
Oto, jak rozwiązałbym twój problem za pomocą monady Może zmonetjs
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..catchinstrukcję. To powiedziawszy, tablica zawierająca szalenie heterogeniczne elementy wygląda dla mnie na problem projektowy.