1. ホーム
  2. javascript

[解決済み] Reduxのreducerはなぜreducerと呼ばれるのですか?

2023-05-17 07:34:08

質問

学習中 Redux に遭遇しました。 Reducers . ドキュメントにはこうあります。

reducerは純粋な関数で、前の状態とアクションを受け取り、次の状態を返します。(previousState, action) => newState. Array.prototype.reduce(reducer, ?initialValue) に渡すようなタイプの関数なので、reducerと呼ばれています。

MDN では reduce というメソッドがあります。

reduce() メソッドは、アキュムレータと配列の各値(左から右へ)に対して関数を適用し、単一の値に縮小します。

Reduxのreducerの定義が意味不明なので、まだ混乱しています。次に、MDN の説明も正しくないようです。その reduce メソッドは常に1つの値に還元するために使われるわけではありません。代わりに使われるのは mapfilter であり、チェーンの代わりに使用すると実際に速くなります。

MDN の記述は間違っていますか?

Reduxのreducerの定義に飛びますと、以下のように記載されています。

Array.prototype.reduce(reducer, ?initialValue) に渡すようなタイプの関数なのでreducerと呼ばれています。

Reduxのreducerは状態を変更する役割を担っている印象がありますね。reducerの例です。

const count = function(state, action) {
    if(action.type == 'INCREMENT') {
        return state + 1;
    } else if(action.type == 'DECREMENT') {
        return state - 1;
    } else {
        return state;
    }
}

... に渡されるような関数であるとは思えません。 reduce . そのデータはどのように1つの値に還元されるのでしょうか?もしこれが reduce では state がコールバックとなり action が初期値となります。

わかりやすい説明ありがとうございます。概念が難しいです。

どのように解決するのですか?

reduce"という用語は、実際には関数型プログラミングで使用される関数用語です。Haskell、F#、あるいはJavaScriptのような言語では、(任意のサイズの)コレクションを入力として受け取り、単一の値を出力として返す変換を定義します。

ですから、(衒学的な意味ではなく、私はこれが役に立つと思うのですが)視覚的に考えてみてください。私たちはコレクションを持っています。

[][][][][][][][][][]

...これは一つの値にまとめたい。

N

プログラミングの機能的には、コレクションの各要素に対して再帰的に呼び出すことのできる1つの関数でこれを行うことになります。しかし、そうすると、どこかで中間値を追跡する必要がありますよね?純粋でない実装では、このように状態を追跡するために、関数の外側で何らかのアキュムレータや変数を保持するかもしれません。

var accumulator = 0;
var myArray = [1,2,3,4,5];

myArray.reduce(function (each) {
    accumulator += 0;
});

return accumulator;

しかし、純粋な関数では、このようなことはできません。なぜなら、定義上、純粋な関数はその関数スコープの外側で効果を持つことができないからです。呼び出しの間に状態をカプセル化する外部変数に依存する代わりに、メソッド内で単に状態を渡します。

var myArray = [1,2,3,4,5];

return myArray.reduce(function (accumulator, each) {
    return accumulator + each;
}, 0);

この場合、この関数はメソッドのシグネチャからquot;reducer"と呼ばれます。次のようになります。 each (または current - でもよい)、コレクション内のオブジェクトを表します。 state (または previous ) があり、これは関数の各反復処理に渡され、コレクション内の前の要素に既に行った変換の結果を表します。

参照した MDN ドキュメントが正しいことに注意してください。 reduce() 関数は常に単一の値を返します。実際 reduce メソッドはどの言語でも 高次関数 で、quot;reducer" (上で定義したメソッドシグネチャを持つ関数) を受け取り、1 つの値を返します。さて、そう、あなたは は、呼び出した関数が副作用を持つ場合、他のことをすることもできますが、そうすべきではありません。 .reduce() を foreach として使ってはいけません)。で呼び出したメソッドが reduce で呼び出したメソッドに副作用があったとしても の戻り値 はコレクションではなく、単一の値になります。

素晴らしいことに、このパターンはReactで見たような配列や具象的なコレクションにだけ適用されるわけではありません。

これが役に立つことを願っています。参考までに、Reduxサイトの定義は改善されるかもしれません(reducerの概念はJavascriptのArrayプロトタイプメソッドのためだけではありませんから)。PRを出すべき!

編集:Wikipediaの記事もありますね。なお、reducerには様々な名称があり、関数型言語では一般的にFoldと呼ばれています。 https://en.wikipedia.org/wiki/Fold_(higher-order_function)#Folds_as_structural_transformations

編集 (2020-10-03)。人々はまだこれを便利だと感じているようです。時間と共に、私は、quot;fold" がこれに対してより良い用語であることに気づきました。