(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-5LHNRP9'); thecodest, Autor na The Codest - Strona 8 z 13

Wprowadzenie

Często utrzymanie niemodyfikowalności jest trudne do utrzymania. Wzorzec zawijania dane do kontenera przychodzi na ratunek. Zabezpiecza on wartości, dzięki czemu korzystanie z nich jest bezpieczne i nie powoduje skutków ubocznych.

Jeśli jesteś tu nowy, koniecznie sprawdź moje ostatnie 2 części dotyczące programowania funkcjonalnego na The Codest blog o:

Funktor

Nie ma złożonej logiki. Jego głównym zadaniem jest opakowywanie kontekstu i wykonywanie na nim funkcji, które otrzymuje z zewnątrz. Za każdym razem, gdy zmienia się wartość, nowa instancja kontenera jest przepakowywana i zwracana. Podczas wywoływania funkcji mapa która wykonuje określoną akcję, zwraca nową instancję kontenera z wartością zwróconą przez przekazaną funkcję, zachowując zasadę niemodyfikowalności.

Deklaracja

 const Functor = value => ({
     map: fn => Functor(fn(value)),
     chain: fn => fn(value),
     of: () => value
 });

mapa - przydatna, gdy chcesz zmienić stan wartości w kontenerze, ale nie chcesz jej jeszcze zwracać.

łańcuch - używany, jeśli chcesz przekazać wartość do funkcji bez modyfikowania stanu kontenera. Zwykle na końcu mapa połączenia.

z - zwraca bieżącą wartość

Przykład imperatywu

const randomInt = (max) => Math.floor(Math.random() * (max + 1))

const randomNumber = randomInt(200) // zwraca liczbę pomiędzy 0 a 200

decrease(randomNumber) // zwraca (liczbę pomiędzy 0 a 200) - 1

Przykład deklaratywny

const randomIntWrapper = (max) =>
Functor(max)
.map(increase) // max + 1
.map(multiplyBy(Math.random())) // Math.random() * (max + 1)
.map(Math.floor) // Math.floor(Math.random() * (max + 1))

const randomNumber = randomIntWrapper(200)

randomNumber.of() // zwraca liczbę pomiędzy 0 a 200
randomNumber.chain(decrease) // zwraca (liczbę między 0 a 200) - 1

Monada

Czasami, oprócz funkcji wywołujących nowy stan wartości, potrzebna jest dodatkowa logika ukryta w kontenerze. Tutaj przydaje się monada, która jest rozszerzeniem funkcji funktor. Może na przykład zdecydować, co powinno się stać, gdy wartość ma określoną wartość lub jaką ścieżkę mają obrać kolejne działania.

Monada może

Monada być może rozwiązuje problem wartości, które nie zwracają prawdy. Kiedy tak się dzieje, kolejne mapa są ignorowane, ale umożliwia zwrócenie alternatywy poprzez wywołanie funkcji getOr method. Pozwala to uniknąć stosowania operatorów if / else, które są popularne w metodach imperatywny programowanie. Monada ta składa się z trzech kontenerów:

Nic - uruchamia się, gdy wartość, która nie jest prawdziwa, wpada do kontenera lub filtr zwraca wartość false. Służy do symulacji wykonania funkcji. Oznacza to, że ten kontener odbiera funkcję, ale jej nie wykonuje.

Po prostu - jest to główny kontener, który wykonuje wszystkie funkcje, ale jeśli wartość zmieni się na wartość false lub filtr zwróci wartość false, przekaże ją do metody Nic pojemnik.

Może - Biorę wartość początkową i decyduję, który kontener wywołać na początku.

Deklaracja

const Just = value => ({
map: fn => Maybe(fn(value)),
chain: fn => fn(value),
of: () => value,
getOr: () => value,
filter: fn => fn(value) ? Just(value) : Nothing(),
type: 'just'
});

const Nothing = () => ({
map: fn => Nothing(),
chain: fn => fn(),
of: () => Nothing(),
getOr: substitute => substitute,
filter: () => Nothing(),
type: 'nothing'
});

const Maybe = value =>
value == null || value == undefined || value.type == 'nothing'
? Nothing()
: Just(value)
tabela metody funktor

Rozbudujmy teraz poprzedni przykład o warunek. Jeśli wartość max jest większa od zera, funkcja zostanie wykonana. W przeciwnym razie funkcja zwróci 0.

Przykład imperatywu

const randomInt = (max) => {
if(max > 0) {
return Math.floor(Math.random() * (max + 1))
} else {
return 0
}
}

const bookMiddlePage = 200

const randomPage = randomInt(10) || bookMiddlePage // zwraca losową wartość
const randomPage = randomInt(-10) || bookMiddlePage // zwraca 200

Przykład deklaratywny

const randomIntWrapper = (max) =>
Maybe(max)
.filter(max => max > 0) // wartość false ignoruje dalsze wywołania
.map(increase)
.map(multiplyBy(Math.random()))
.map(Math.floor)

const bookMiddlePage = 200

// Tylko kontener
const randomPage = randomIntWrapper(10).getOr(bookMiddlePage) // zwraca losową wartość
// Kontener bez niczego
const randomPage = randomIntWrapper(-10).getOr(bookMiddlePage) // zwraca 200


baner współpracy

pl_PLPolish