为什么将Redux减速器称为减速器?

问题描述:

在学习 Redux 的同时,我遇到了 Reducers .该文档指出:

Whilst learning Redux I've came across Reducers. The documentation states:

reduceer是一个纯函数,它采用上一个状态和一个动作,然后返回下一个状态.(previousState,操作)=> newState.之所以称为简化器,是因为它是传递给Array.prototype.reduce(reducer,?initialValue)的函数类型.

The reducer is a pure function that takes the previous state and an action, and returns the next state. (previousState, action) => newState. It's called a reducer because it's the type of function you would pass to Array.prototype.reduce(reducer, ?initialValue) .

MDN将 reduce 方法描述为:

MDN describes the reduce method as:

reduce()方法对一个累加器和数组中的每个值(从左到右)应用一个函数,以将其减小为单个值.

The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.

我仍然对为什么Redux定义reducer感到困惑,因为它没有意义.其次,MDN描述似乎也不正确. reduce 方法并不总是用于减少为单个值.可以使用它代替 map filter ,并且在代替链接时实际上更快.

I'm still confused on why the Redux definition of a reducer as it's making no sense. Secondly the MDN description doesn't seem correct either. The reduce method isn't always used to reduce to a single value. It can be used in place of map and filter and is actually faster when used in place of chaining.

MDN描述不正确吗?

Is the MDN description incorrect?

跳回到Redux的reducer定义,它指出:

Jumping back to the Redux definition of a reducer, it states:

之所以称为简化器,是因为它是传递给Array.prototype.reduce(reducer,?initialValue)的函数类型

It's called a reducer because it's the type of function you would pass to Array.prototype.reduce(reducer, ?initialValue)

我的印象是Redux中的reducer负责修改状态.减速器示例:

I'm under the impression that a reducer in Redux is responsible for modifying state. An example 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 的函数.该数据如何减少为单个值?如果这是一个函数,您将传递给 reduce ,则 state 将是回调,而 action 将是初始值.

... I don't see how this is a function that would be passed to reduce. How is that data being reduced to a single value? If this is a function you would pass to reduce then state would be the callback and action would be the initial value.

感谢您提供任何清晰的解释.很难概念化.

Thanks for any clear explanations. It's difficult to conceptualize.

"reduce"一词实际上是函数编程中使用的一个函数术语.在Haskell,F#甚至JavaScript之类的语言中,我们定义了一个转换,该转换将一个集合(任何大小)作为输入,并返回一个值作为输出.

The term "reduce" is actually a functional term used in functional programming. In a language like Haskell, F# or even JavaScript, we define a transformation that takes a collection (of any size) as input and returns a single value as output.

所以(不要太学究了,但是我发现这对我有帮助)从视觉上考虑它.我们有一个收藏集:

So (not to be pedantic, but I find this helps me) think of it visually. We have a collection:

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

...我们希望将其折叠为一个值:

...which we want to collapse into a single value:

N

从功能上进行编程,我们将使用单个函数来执行此操作,我们可以对集合的每个元素进行递归调用.但是,如果这样做,则需要在某个地方跟踪中间值,对吗?非纯实现可能会保留某种累加器".或函数外部的变量来跟踪状态,例如:

Programming functionally, we would do this with a single function that we could call recursively on each element of the collection. But if you do that, you need to keep track of the intermediate value somewhere, right? Non-pure implementations might keep some kind of "accumulator" or variable outside of the function to keep track of the state, like so:

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

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

return accumulator;

但是,对于纯函数,我们无法做到这一点-因为根据定义,纯函数不会在其函数范围之外产生影响.与其依赖于封装我们的状态"的外部变量,不如依赖于外部变量.在调用之间,我们只需在方法中传递状态:

With pure functions, though, we can't do this - because by definition, pure functions can't have effects outside of their function scope. Instead of relying on an external variable that encapsulates our "state" between calls, we simply pass the state along in the method:

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

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

在这种情况下,我们称该函数为"reducer".由于其方法签名.我们有 each (或 current -任何名称都可以),代表集合中的一个对象;和 state (或 previous ),它们传递给函数的每个迭代,代表我们已经对集合中的先前元素进行的转换的结果.

In this case we call the function a "reducer" because of its method signature. We have each (or current - any name is fine), representing an object in the collection; and state (or previous), which is passed to each iteration of the function, representing the results of the transformation we've already done to the previous elements in the collection.

请注意,您所引用的MDN文档是正确的. reduce()函数始终会返回单个值.实际上,任何语言的 reduce 方法都是高阶函数,其中包含一个"reducer".(具有上面定义的方法签名的函数)并返回单个值.现在,是的,如果您调用的函数具有副作用,但您可以使用它做其他事情,但您不应该这样做.(本质上,请勿将 .reduce()用作foreach.)即使您使用 reduce 调用的方法有副作用,返回值的em>将是一个值,而不是一个集合.

Note that the MDN documentation you referenced is correct; the reduce() function always does return a single value. In fact, the reduce method in any language is a higher-order function that takes a "reducer" (a function with the method signature defined above) and returns a single value. Now, yes, you can do other stuff with it, if your function that you call has side effects, but you shouldn't. (Essentially, don't use .reduce() as a foreach.) Even if the method you call with reduce has side effects, the return value of reduce itself will be a single value, not a collection.

很棒的事情是,这种模式不仅仅适用于数组或具体的集合,就像您在React中看到的那样;这种模式也可以应用于流,因为它们是纯函数.

The cool thing is, this pattern doesn't just have to apply to arrays or concrete collections, as you've seen in React; this pattern can be applied to streams as well, since they're pure functions.

希望这会有所帮助.就其价值而言,可以改进Redux站点上的定义(因为reducer的概念不仅仅是因为Javascript的Array原型方法).您应该提交PR!

Hope this helps. For what it's worth, the definition on the Redux site could be improved (as the concept of a reducer isn't just because of Javascript's Array prototype method). You should submit a PR!

关于此主题,有Wikipedia文章.请注意,reduce具有不同的名称,并且在功能语言中,通常称为Fold. https://en.wikipedia.org/wiki/Fold_(higher-order_function)#Folds_as_structural_transformations

There's a Wikipedia article on the subject. Note that reduce has different names, and in functional languages, it's commonly known as Fold. https://en.wikipedia.org/wiki/Fold_(higher-order_function)#Folds_as_structural_transformations

编辑(2020-10-03):人们似乎仍然发现这很有用-很好.随着时间的流逝,我已经意识到折叠"是一种折".这是一个更好的术语;功能语言正确无误.异径管"并不是一个坏词,但这也不一定是一个好词.

Edit (2020-10-03): People still seem to be finding this useful - that's good. With time, I've realized that "fold" is a much better term for this; the functional languages got it right. "Reducer" isn't really a bad term, but it's not necessarily a good one, either.