为什么Redux减速机称为减速机?

Bug*_*rUK 40 javascript functional-programming reactjs redux

虽然学习Redux我遇到了Reducers.文件说明:

reducer是一个纯函数,它接受前一个状态和一个动作,并返回下一个状态.(previousState,action)=> newState.它被称为reducer,因为它是你传递给Array.prototype.reduce(reducer,?initialValue)的函数类型.

MDN将该reduce方法描述为:

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

我仍然对Redux定义减速器的原因感到困惑,因为它没有任何意义.其次,MDN描述似乎也不正确.该reduce方法并不总是用于减少单个值.当用于代替链接时,它可以用来代替mapfilter实际上更快.

MDN描述不正确吗?

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

它被称为reducer,因为它是你传递给Array.prototype.reduce(reducer,?initialValue)的函数类型

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

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

...我不知道这是一个传递给它的函数reduce.如何将数据减少到单个值?如果这是一个你传递给的函数reduce那么state将是回调并且action将是初始值.

谢谢你有任何明确的解释.这很难概念化.

jed*_*ung 30

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

所以(不要迂腐,但我发现这有助于我)从视觉上思考它.我们有一个集合:

[][][][][][][][][][]
Run Code Online (Sandbox Code Playgroud)

...我们想要折叠成单个值.

N
Run Code Online (Sandbox Code Playgroud)

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

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

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

return accumulator;
Run Code Online (Sandbox Code Playgroud)

但是,对于纯函数,我们不能这样做 - 因为根据定义,纯函数不能在函数范围之外产生影响.相反或依赖于在调用之间封装我们的"状态"的外部变量,我们只是在方法中传递状态.

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

return myArray.reduce(function (accumulator, each) {
    return accumulator + each;
}, 0);
Run Code Online (Sandbox Code Playgroud)

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

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

关于这一点很酷,这个模式不仅仅适用于数组或具体集合,正如你在React中看到的那样; 这种模式也可以应用于流,因为它们是纯函数.

希望这可以帮助.对于它的价值,可以改进Redux站点上的定义(因为reducer的概念不仅仅是因为Javascript的Array原型方法).你应该提交公关!

编辑:有关于这个主题的维基百科文章.请注意,reduce具有不同的名称,在函数式语言中,它通常称为Fold.https://en.wikipedia.org/wiki/Fold_(higher-order_function)#Folds_as_structural_transformations


ava*_*he1 16

将 Redux减速器称为减速器在语义上是不正确的并且没有多大意义。这就是作者困惑的原因。

缩减器是一种将一组值缩减为单个值的函数
我们也可以说它折叠了值- 因此是函数式编程中的经典fold()fn 。

由于 Redux reducer不会折叠一组值,而是将一个操作应用于一个状态并始终返回相同的形状 ( State -> Action -> State) - 它应该被称为applicatorapplier
但是,由于我们必须始终返回相同形状的状态,而不仅仅是完全不相关的东西 - 我们更有意义地调用 Redux 状态应用程序 -转换器转换器mutators
而且,使用“改变状态”“状态突变器”等术语确实已经变得司空见惯。

但 Redux 听起来比AppluxMutux酷多了:)

  • 多么美妙的答案啊。谢谢你。Reducer 不是一个准确的名称 - 但正如你所说 - Applux、Mutux 听起来很糟糕。我猜,适当的命名惯例和营销并不相辅相成! (5认同)

cod*_*kix 11

为什么一个原因Redux的减速机被称为reducer是因为你可以"减少"一个collection of actionsinitial state(实体店),要执行这些操作,以获得由此而来final state.

怎么样?要回答这个问题,让我再次定义一个减速器:

减少()方法施加function (reducer)针对accumulator与阵列的每个值(从左到右),以将其降低到一个值.

redux减速机有什么作用?

reducer是一个pure function,它接受当前状态和一个动作,并返回下一个状态.请注意,状态是accumulated应用集合上的每个操作来更改此状态.

因此,给定a collection of actions,reducer应用于集合的每个值(从左到右).第一次,它返回initial value.现在,reducer再次应用于此初始状态,并且第一个操作将返回下一个状态.并且每次应用下一个集合项(动作)current state以获得next state直到它到达数组的末尾.然后,你得到the final state.多么酷啊!

  • 最好的解释...我仍然认为它的名字用起来很糟糕...商店不是传统意义上的真正的功能累加器,它比那更复杂。StoreModifier 似乎更好 =) (3认同)

Bla*_*ula 6

抱歉,但我不同意以前的答案。我支持命名reducer。我对FP和不变性充满热情。不要怪我,阅读第二部分,但是我想先说一下,为什么我不同意。

减速器是转换序列是正确的,但是序列本身-可以是另一个序列的一部分。想象一下,就像链接-链的一部分。但是,链本身可能是较长链的一部分。每个链接都是全局状态的“过渡”。比,背后的理论是什么?

它实际上不是“有限状态机”吗?-关闭,但不行。实际上是过渡系统

标记的过渡系统是元组(S,?,?),其中S是一组状态,?是一组标签和?是一组标记的过渡

所以S-是我们的状态

?-是我们所谓的“动作”(但理论上是标签

...和

?- 减速器 “标记为过渡”!如果我是这个库的创建者,我会这样命名。

理解这个理论帮我实现我的图书馆,在那里我可以有低电平迁移系统的一部分高电平迁移系统(如链-仍然可能会更长链的一部分) -现在依然有单一的全球Redux的状态。

  • 我之所以在图书馆中苦苦挣扎,仅仅是因为我无法通过'reducer'命名法……知道其他人也为这个名字而苦恼实际上对我很有帮助。上面的@ code4kix定义也有帮助 (6认同)

Tha*_*you 5

我的印象是 Redux 中的减速器负责修改状态。一个示例减速器:

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

...我不明白这是一个如何传递给reduce的函数。这些数据是如何减少到单个值的?如果这是一个您将传递给 reduce 的函数,那么 state 将是回调,而 action 将是初始值。

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