Dlaczego funkcje stanu Reduxa nazywane są reduktorami?

82

To jest część oficjalnej dokumentacji Redux :

Nazywa się to reduktorem, ponieważ jest to typ funkcji, do której możesz przejść Array.prototype.reduce(reducer, ?initialValue)

Nie ma to dla mnie większego sensu. Czy ktoś mógłby mi wyjaśnić, dlaczego tak naprawdę nazywa się je reduktorami? Fakt, że zwracają wartość domyślną (lub mają domyślną wartość argumentu), nie sprawia, że ​​redukują IMHO.

Anton Savchenko
źródło
6
Są to reduktory dokładnie dlatego, że zachowują się jak funkcja, do reducektórej przekazujesz , która ma dostęp do wartości domyślnej i innej wartości, i zwraca potencjalnie przekształconą wartość domyślną. state -> action -> state
azium
2
róża pod inną nazwą… prawdopodobnie marketingowa; mapa / redukuj to teraz modne hasło ...
dandavis
1
dlatego musisz zacząć myśleć samodzielnie i nie polegać na frameworku. Framwork to w większości praca jednego lub kilku programistów z własną wizją rozwiązania problemu zaadaptowanego przez internautów. Niektóre frameworki mają rację, ale w większości nie. zamieć pocałunku, to samo lub mniej nie jest rozwiązaniem. To tylko przykład wielu z nich.
Codebeat

Odpowiedzi:

71

Fakt, że zwracają wartość domyślną (lub mają domyślną wartość argumentu), nie sprawia, że ​​redukują IMHO.

Reduktory nie zwracają tylko wartości domyślnych. Zawsze zwracają akumulację stanu (na podstawie wszystkich poprzednich i bieżących działań).

Dlatego działają jako reduktory stanu. Za każdym razem, gdy wywoływany jest reduktor redux, stan jest przekazywany z akcją (state, action). Stan ten jest następnie redukowany (lub kumulowany) na podstawie działania, a następnie zwracany jest następny stan. To jeden cykl klasyki foldlub reducefunkcji.

Jak podsumował @azium state -> action -> state.

Davin Tryon
źródło
7
Czyż nie powinniśmy nazywać ich raczej zwiększaczami niż reduktorami? Żadne dane nie są nigdy zmniejszane, a ich dodawanie: / lol
Jamie Hutber
16
@JamieHutber Myślę, że w tym kontekście nieco brakuje ci znaczenia reduktora. reduktor pobiera strumień (lub kolekcję) elementów i łączy je w jeden element. W tym przypadku wszystkie działania (w czasie) są zbiorem elementów, a stan to pojedynczy element. Ma sens?
Davin Tryon,
7
lol teraz rozumiem. Więc to po prostu konkludowanie ich. Dlaczego więc nie nazwać tego połączeniem: P Dziękuję za wyjaśnienie mi :)
Jamie Hutber
20
Dzięki Bogu, nie jestem jedyny, który uważa, że ​​nazwa reduktora jest nieco niższa o co najmniej 2000 wyświetleń tego postu w czasie, gdy to piszę. Fakt, że ktoś jest nawet skłonny do podkręcenia wysiłku, aby wykopać, dlaczego nazywa się to reduktorem, czy nie oznacza to, że rzeczywiście jest trochę nie tak? Jeśli nazywa się to reduktorem, ponieważ jest to typ funkcji, który można przekazać do Array.prototype.reduce, to tak, jakbyśmy nazwali pomarańczowy sokowirówką, ponieważ przekazujemy pomarańczowy do object.prototype.juicer, czy nie powinniśmy nazywać tego owocem?
Yini,
2
Zgadzam się, to wcale nie jest intuicyjna nazwa. Logicznie rzecz biorąc, aby nazywać się reduktorem, powinno coś redukować. Gdyby wymagało całego szeregu zmian stanu wraz ze stanem i łączyło je w jeden stan jednocześnie, byłaby to nazwa intuicyjna.
Peter Evan Deal
20

Jeśli uważasz, że seria działań w Twojej aplikacji przypomina listę, a może bardziej strumień, może to mieć większy sens.

Weźmy ten wymyślony przykład:

['apple', 'banana', 'cherry'].reduce((acc, item) => acc + item.length, 0)

Pierwszy argument jest funkcją formularza (Int, String) => Int. Wraz z wartością początkową przekazujesz reducecoś, co można by nazwać „funkcją redukującą”, i otrzymujesz wynik przetwarzania serii elementów. Można więc powiedzieć, że funkcja reduktora opisuje, co jest robione z każdym kolejnym pojedynczym elementem, aby zmienić wynik. Innymi słowy, funkcja reduktora pobiera poprzednią wartość wyjściową i następną wartość i oblicza następną wartość wyjściową.

Jest to analogiczne do tego, co robi reduktor Redux: przyjmuje poprzedni stan i bieżącą akcję i oblicza następny stan.

W prawdziwym funkcjonalnym stylu programowania można koncepcyjnie wymazać znaczenie przypisane argumentom i wynikom, a po prostu skupić się na „kształcie” danych wejściowych i wyjściowych.

W praktyce reduktory Redux są zazwyczaj ortogonalne, w tym sensie, że dla danego działania nie wszystkie wprowadzają zmiany w tych samych właściwościach, co ułatwia podzielenie ich obowiązków i agregowanie wyników combineReducers.

acjay
źródło
Tak, masz rację, ma to większy sens, gdy myślę o działaniach bardziej jak o strumieniu. Super, przeproś to!
Anton Savchenko
Tak to początkowo rozumiałem, ale nie wydaje się, aby tak było w żadnej z implementacji sklepu, które widziałem do tej pory ...
Boris Callens,
16

Jak już wspomniano, nazwa związana jest z koncepcją reduktora w programowaniu funkcyjnym. Pomocna może być również słownikowa definicja reduktora Merriam-Webster:

1a. zebrać razem lub spowodować zbieżność: skonsolidować (zredukować wszystkie pytania do jednego)

Reduktor konsoliduje działania w jeden obiekt reprezentujący stan aplikacji.

Drew Goodwin
źródło
8

Powodem, dla którego reduktor redux jest nazywany a, reducerjest to, że można „zredukować” a collection of actionsi initial state(ze sklepu), na których należy wykonać te czynności, aby uzyskać wynik final state.

W jaki sposób? Aby odpowiedzieć na to pytanie, jeszcze raz zdefiniuję reduktor:

Metoda redukuj () stosuje a function (reducer)względem wartości accumulatori każdej wartości tablicy (od lewej do prawej), aby zredukować ją do jednej wartości.

A co robi reduktor Redux?

Reduktor jest czysty, functionktóry przyjmuje bieżący stan i akcję i zwraca następny stan. Należy zauważyć, że stan jest taki, accumulatedjak każda akcja w kolekcji jest stosowana w celu zmiany tego stanu.

Więc biorąc pod uwagę a collection of actions, reduktor jest stosowany do każdej wartości kolekcji (od lewej do prawej). Za pierwszym razem zwraca initial value. Teraz reduktor jest ponownie stosowany w tym stanie początkowym i pierwsza akcja przywraca następny stan. I następny element kolekcji (akcja) jest wykonywany za każdym razem, current stateaby uzyskać, next stateaż osiągnie koniec tablicy. A potem masz the final state. Jakie to jest świetne!

code4kix
źródło
5

Autor uważa stan za akumulator funkcji redukcji. Dawny:

Final State = [Action1, Action2, ..., ActionN].reduce(reducer, Initial State);

Funkcja redukcji pochodzi z programowania funkcyjnego, nazwa „reduktor” również pochodzi od FP.

Nie lubię używać tej nazwy tutaj. Ponieważ nie postrzegam świata jako jednej wartości wynikającej z działań. Państwo tutaj jest przedmiotem. Na przykład:

['eat', 'sleep'] === [addTodo('eat'), addTodo('sleep')].reduce(reducer, []);

Ten reduktor w ogóle niczego nie redukuje. I nie obchodzi mnie to, czy cokolwiek redukuje, czy nie. Nazwanie go przetwornikiem będzie miało większy sens.

joshmori
źródło
5

Wiemy, skąd pochodzą Reduktory (programowanie funkcjonalne) i dlaczego można je uznać za redukujące pracę (zredukować n elementów wejściowych do pojedynczej wartości zwracanej - co jest właśnie tym, co zwykle robią). Jednak: nazwa to tylko nazwa, tak jak róża to nazwa róży. Nie myśl za dużo. Programiści Redux to ludzie IT, są zamknięci w swoim kontekście i tam ma to sens. Reszta z nas musi zaakceptować prawo wynalazcy do nazwania niebieskiego psa żółtym kotem ;-)

René Baron
źródło
2

Co powiesz na to, że od teraz będziemy go nazywać Deducer . Wyprowadza nowy stan na podstawie poprzedniego stanu i nadchodzącej akcji.

Rutger van Dijk
źródło
1

Nie należy ich nazywać redukować, ponieważ redukcja oznacza mniej, te funkcje najczęściej dają więcej. a następnie zwróć

nacięcie
źródło
1

Nie mogłem zobaczyć, jak reduktor Redux jest bezpośrednio mapowany na funkcję, z której korzystasz reduce, więc oto kilka przykładów, aby zobaczyć, jak pasują.

Najpierw standardowa funkcja reduktora (nazywana w MDN „akumulatorem”) z dokumentacji MDN Array.reduce, a następnie uproszczony przykład Dana Abramova Counter.jsna końcu jego wpisu na blogu „Możesz nie potrzebować Redux” .

  • sum dodaje wartość do akumulatora
  • reducer dodaje / odejmuje wartość do / z akumulatora.

W obu przypadkach „stan” jest po prostu liczbą całkowitą.

„Kumulujesz” działania w stanie. Jest to również niezmienny sposób modyfikowania dowolnego obiektu JavaScript.

const sum = function(acc, val) {
    return acc + val;
};

const reducer = function(state, action) {
    switch (action) {
        case 'INCREMENT':
            return state + 1;
        case 'DECREMENT':
            return state - 1;
        default:
            return state;
    }
};

console.log('sum', [1, -1, 1].reduce(sum, 0));

console.log('reduce', ['INCREMENT', 'DECREMENT', 'INCREMENT'].reduce(reducer, 0));

console.log('sum', [1, 1, 1].reduce(sum, 0));

console.log('reduce', ['INCREMENT', 'INCREMENT', 'INCREMENT'].reduce(reducer, 0));

icc97
źródło
0

Inne odpowiedzi dobrze wyjaśniają, dlaczego nazywa się tak, jak jest, ale spróbujmy nazwać więcej rzeczy ...

const origState = 0;
const actionOperators = {
    increment: (origState) => origState++,
    decrement: (origState) => origState--,
};
const anOperator = (aState, anAction) => actionOperators[anAction](aState);
const actions = ['increment', 'decrement', 'increment'];
const finalState = actions.reduce(anOperator, origState);

Po pierwsze, reducemożna nazwać use anOperator with every action name and accumulated state, starting with origState. W smalltalk to się nazywa actions inject: origState into: anOperator. Ale co właściwie wstrzykujesz operatorowi? OrigState ORAZ nazwy akcji. Więc nawet w Smalltalk nazwy metod nie są zbyt jasne.

actionOperators[increment]jest reduktorem, ale raczej nazwałbym go i actionOperator, ponieważ jest zaimplementowany dla każdej akcji. Stan to tylko argument (i kolejny jako wartość zwracana).

Reducer jest jednak lepszym słowem, aby znaleźć się na szczycie wyników wyszukiwania Google. Jest również podobny do Redux.

Rivenfall
źródło
0

W poniższym kodzie wystarczy pomyśleć o akumulatorze jako akcjach, a currentValue jako o stanie w kontekście redux. z tego przykładu dowiesz się, dlaczego nazywają go również reduktorem.

const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;

// Main operation is 1 + 2 + 3 + 4 = 10
// but think of it as a stack like this: 

// | 2 | | 3 | | 4 | 
// |_1_| |_3_| |_6_| | 10 | => the 10 is in result

console.log(array1.reduce(reducer));
// expected output: 10

Metoda REDUKCJA () wykonuje funkcję reduktora (którą podajesz) na każdym elemencie tablicy, w wyniku czego powstaje pojedyncza wartość wyjściowa.

Ehsan Ahmadi
źródło