在学习Redux
时,我遇到了Reducers
。文档指出:
reducer 是一个纯函数,它接受前一个状态和一个操作,并返回下一个状态。(previousState,action) = & gt;newState。它被称为 reducer,因为它是您将传递给 Array.prototype.reduce (reducer,?initialValue) 的函数类型。
MDN 将reduce
方法描述为:
reduce () 方法对累加器和数组的每个值(从左到右)应用一个函数,以将其减少到单个值。
reduce
方法并不总是用于减少单个值。它可以代替map
和filter
使用,当代替链接使用时,它实际上更快。
MDN 描述不正确吗?
跳回到减速器的 Redux 定义,它指出:
它被称为 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;
}
}
...我不明白这是一个如何传递给reduce
的函数。如何将数据减少到一个值?如果这是一个函数,你将传递给reduce
,那么state
将是回调,action
将是初始值。
感谢任何明确的解释。这很难概念化。
术语“reduce”实际上是函数式编程中使用的函数术语,在 Haskell,F # 甚至 JavaScript 等语言中,我们定义了一个转换,该转换将(任何大小的)集合作为输入,并返回单个值作为输出。
所以(不要迂腐,但我发现这有助于我)从视觉上思考它。我们有一个集合:
[][][][][][][][][][]
...我们想要折叠成一个值:
N
在功能上进行编程,我们将使用一个函数来做到这一点,我们可以在集合的每个元素上递归调用。但是如果你这样做,你需要跟踪某个地方的中间值,对吗?非纯实现可能会在函数之外保留某种“累加器”或变量来跟踪状态,如下所示:
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);
在这种情况下,由于其方法签名,我们将函数称为“reducer”。我们有each
(或current
-任何名称都可以),表示集合中的对象;和state
(或previous
),它传递给函数的每次迭代,表示我们已经对集合中的先前元素进行的转换的结果。
请注意,您引用的 MDN 文档是正确的;reduce()
函数本身总是返回一个值。实际上,任何语言中的reduce
方法都是一个higher-order function,它接受一个“reducer”(具有上面定义的方法签名的函数)并返回一个值。现在,是的,您可以用它做其他事情
很酷的事情是,这种模式不只适用于数组或具体集合,正如你在 React 中看到的;这种模式也可以应用于流,因为它们是纯函数。
希望这有帮助。对于它的价值,Redux 网站上的定义可以改进 (因为 reducer 的概念不仅仅是因为 Javascript 的 Array 原型方法)。你应该提交一个 PR!
编辑:有一篇关于这个主题的文章。请注意,reduce 有不同的名称,在函数式语言中,它通常被称为 Fold。https://en..org/wiki/Fold_(higher-order_function)#Folds_as_structural_transformations
编辑(2020-10-03):人们似乎仍然发现这个有用的-这很好。随着时间的推移,我意识到“折叠”是一个更好的术语;函数式语言得到了它的权利。
之所以将redux reducer称为reducer
,是因为您可以“减少”对其执行这些操作以获得结果final state
的collection of actions
和initial state
(商店)。
如何?为了回答这个问题,让我再次定义一个减速器:
reduce()方法对accumulator
和数组的每个值(从左到右)应用function (reducer)
以将其减少为单个值。
redux 减速器有什么作用?
reducer 是一个纯function
,它接受当前状态和一个操作,并返回下一个状态。请注意,状态是accumulated
,因为集合上的每个操作都用于更改此状态。
所以给定一个collection of actions
,reducer 应用于集合的每个值 (从左到右)。第一次,它返回initial value
。现在 reducer 再次应用于这个初始状态和第一个操作以返回下一个状态。而下一个集合项 (action) 每次都应用于current state
以获得next state
的数组如何结束!
对不起,但我不同意以前的答案。我不会支持命名reducer
。我对 FP 和不变性充满热情。不要怪我,阅读第二部分,但我想先说明一下,为什么我不同意。
这是正确的,化简是变换的序列,但序列本身-可能是另一个序列的一部分。想象一下,像链接-链的一部分。但是链本身可能是更长的链的一部分。每个链接都是全局状态的“过渡”。比,它背后的理论是什么?
它实际上不是“有限状态机”吗?-close,但不是。它实际上是Transition system。
带标签的过渡系统是一个元组(S,Λ,→),其中 S 是一组状态,Λ 是一组标签,并且 → 是一组带标签的过渡
所以,S
-是我们的状态集
Λ
-是我们所谓的“动作”(但理论上是标签)
...and
→
-reducers“标记的转换”!如果我是这个库的创建者,我会这样命名它。
理解这个理论帮助我实现了我的库,在那里我可以有低级转换系统作为高级转换系统的一部分(像链-仍然可以是更长链的一部分)-并且仍然具有单个全局 Redux 状态。
调用 Redux reducersreducers在语义上是不正确的,并且没有太大意义,这就是作者感到困惑的原因。
reducer 是一个函数,它将一组值减少为一个值。
我们也可以说它折叠值-因此是函数式编程中的经典fold()
fn。
由于 Redux reducer和 commonator不会像它一样折叠一组值,而是将一个动作应用于一个状态,并始终返回相同的形状(State -> Action -> State
)-它应该被称为applicator或applicier。
但是,由于我们必须始终返回相同的形状,因此我们
但是 Redux 听起来比Applux或Mutux更酷:)
本站系公益性非盈利分享网址,本文来自用户投稿,不代表边看边学立场,如若转载,请注明出处
评论列表(19条)