Ramda.js 为什么compose应用从左到右的传感器?
示例代码:Ramda.js 为什么compose应用从左到右的传感器?,ramda.js,javascript,functional-programming,transducer,Ramda.js,Javascript,Functional Programming,Transducer,示例代码: // Compose functionality const compose = (...fns) => { return args => { return fns.reduceRight((arg, fn) => fn(arg), args); } }; // List of transformation and predicate functions const add1 = x => x + 1; const isGreaterThan
// Compose functionality
const compose = (...fns) => {
return args => {
return fns.reduceRight((arg, fn) => fn(arg), args);
}
};
// List of transformation and predicate functions
const add1 = x => x + 1;
const isGreaterThanThree = x => x > 3;
const times2 = x => x * 2;
// Concat and Sum reducers (or the thing that I want to build).
/*
In this case, I'm using concatReducer, but I can easily substitute concatReducer with
sumReducer and change the initial value of the reduce method to zero.
*/
const concatReducer = (acc, el) => acc.concat(el);
const sumReducer = (acc, el) => acc += el;
// Transformation reducer (not sure the appropriate terminology)
const mapReducer = transform => {
return reducer => {
return (acc, el) => {
return reducer(acc, transform(el));
}
}
};
// Predicate reducer (again, not sure the appropriate terminology here)
const filterReducer = predicate => {
return reducer => {
return (acc, el) => {
return predicate(el) ? reducer(acc, el) : acc;
}
}
}
[1, 2, 3]
.reduce(
compose(
mapReducer(times2),
filterReducer(isGreaterThanThree),
mapReducer(add1),
)(concatReducer),
[]
);
我希望值是[8],而不是[5,7]
Compose是右关联(reduceRight),但在本例中,它的行为与左关联相同
我心里想,也许我的compose函数实现是错误的。
结果,我使用了R.compose,但得到了相同的结果
我做错什么了吗?或者,在处理传感器时,这是一种组合为左关联的场景吗?引号和一些示例取自 什么是传感器? 传感器只是一个数的函数。唯一的参数是另一个传感器变压器(在代码库中标记为xf) 由于传感器只是一个参数的函数,因此可以通过函数组合轻松组合传感器,以创建变压器管道。请注意,传感器在调用时返回变压器 示例:(改编)
var映射器=函数(f){
返回函数(xf){/因为将组合传感器(f,g,h
)应用于减速器(r
),最左边的(f
)变为最上面的,首先作用于最终参数(acc,el)
到增广减速器f(g(h(r))
:(*)
(*)因此您定义了函数,以便
mapReducer(foo)(reducer)(acc, el)
=~= reducer(acc, foo(el));
filterReducer(predicate)(reducer)(acc, el)
=~= predicate(el) ? reducer(acc, el) : acc;
concatReducer(acc, el)
=~= acc.concat(el);
最重要的是
compose(f,g,h,...,p,q)(r)
=~= [f,g,h,...,p,q].reduceRight((acc, fn) => fn(acc), r);
=~= f(g(h(...(p(q( r ))...)))
那么
[1, 2, 3]
.reduce(
compose(
f, // f = mapReducer(times2),
g, // g = filterReducer(isGreaterThanThree),
h // h = mapReducer(add1),
)(r), // r = concatReducer
[]
)
=~= [1, 2, 3] .reduce( f(g(h(r))), []) // rc = f(g(h(r)))
=~= rc( rc( rc( [], 1), 2), 3)
=~= rc( rc( f(g(h(r)))( [], 1), 2), 3)
=~= rc( rc( mapReducer(times2)(g(h(r)))( [], 1 ), 2), 3)
// mapReducer(foo )(reducer)(acc, el)
// =~= reducer( acc, foo(el))
=~= rc( rc( g(h(r))([], times2( 1)), 2), 3)
=~= rc( rc( filterReducer(isGreaterThanThree)(h(r))([] , times2( 1)),
2),
3)
// filterReducer(pred )(reducer)(acc, el)
// =~= pred(el) ? reducer( acc, el) : acc
=~= rc( rc( isGreaterThanThree( twice1) ? h(r)( [], twice1) : [],
2), /* where twice1 = times2(1)
h = mapReducer( add1) */
3)
=~= rc( rc( isGreaterThanThree( twice1) ? r([], add1(twice1)) : [],
2), /* where twice1 = times2(1)
r = concatReducer */
3)
=~= rc( rc( isGreaterThanThree( twice1) ? [].concat(add1(twice1)) : [],
2), /* where twice1 = times2(1) */
3)
=~= ...
我们可以看到,mapReducer(times2)
首先开始处理列表的元素,然后按进行过滤,其效果大于三个,然后是add1
的映射
在处理[1,2,3]
时,首先完成时间2
的映射(隐式地好像使其成为[2,4,6]
),然后过滤(只剩下[4,6]
),然后映射add1
,最终结果实际上是[5,7]
虽然没有创建中间结构,但却构建了一个复合减速器,由一个reduce
使用,一步一步地沿着输入前进
因此,传感器是一种融合/分解技术。直观地说,嵌套褶皱应该融合,不需要通过内部褶皱创建临时结构,只有这样才能被包裹褶皱消耗;遵循传感器规程,我们才能实现这一点
因此,mapReducer
和filterReducer
的名称很糟糕。它们实际上是mappingTransducer\u-Maker
(或justmappingTransducer\u-Maker
)和filteringTransducer\u-Maker
(或justfilteringTransducer
),其中
mapping(foo)
是一种将foo
应用于输入元件elt
,从而产生foo(elt)
,以及
filtering(pred)
是一种过滤传感器,它根据谓词调用pred(el)
过滤掉输入元素el
,或将其保留在其中
或者更确切地说,传感器增加其变元减速机
,这样,当累加器和当前元素最终调用组合的、增加的减速机时,它在将结果传递到基本减速机
之前,以规定的方式操纵元素和累加器:
mapping(foo)( filtering(pred)(reducer) )( acc, elt)
----------------------------------------( )
=~=
filtering(pred)(reducer)( acc, foo(elt) )
=~=
pred( foo(elt) ) ? reducer( acc, foo(elt) ) : acc
因此,映射(foo)
和过滤(pred)
是根据他们的参数从右到左合成的,reducer
;但是合成的reducer从顶部开始工作,从左到右跟踪传感器的效果——首先进行映射,然后进行过滤。我问了一次,得到了。也许这有助于为迟来的答复道歉。如果我错了,请更正,但在我的例子中,concatReducer的组合仍然是从右到左,首先应用mapReducer(times2)、filterReducer(IsGreaterThree),然后应用mapReducer(add1),后者返回一个接受参数(x)的包装函数。然而,当x传递到包装函数时,x实际上进入mapReducer(times2)首先是其他功能。是否正确?@FNMT8L9IN82映射减速机和过滤器减速机实际上是传感器,而不是减速机。您合成传感器,合成的传感器应用于concatReducer,从而产生一个增强的减速机,用于实际元素和累加器版本(随着输入的进行而变化)。[1,2,3]。reduce(f(g(h(r)),[])=[2,3]。reduce(f(g(h(r)),f(g(h(r))([],1))
根据reduce
的定义。reducer接受对,(acum,elemt)
。因此x
在我的compose
中是一对(acum,elemt)
。这是象征性的。如果需要,请毫不犹豫地询问更多信息。:)感谢您的回复…我需要阅读多次才能理解这一点。
compose(f,g,h,...,p,q)(r)
=~= [f,g,h,...,p,q].reduceRight((acc, fn) => fn(acc), r);
=~= f(g(h(...(p(q( r ))...)))
[1, 2, 3]
.reduce(
compose(
f, // f = mapReducer(times2),
g, // g = filterReducer(isGreaterThanThree),
h // h = mapReducer(add1),
)(r), // r = concatReducer
[]
)
=~= [1, 2, 3] .reduce( f(g(h(r))), []) // rc = f(g(h(r)))
=~= rc( rc( rc( [], 1), 2), 3)
=~= rc( rc( f(g(h(r)))( [], 1), 2), 3)
=~= rc( rc( mapReducer(times2)(g(h(r)))( [], 1 ), 2), 3)
// mapReducer(foo )(reducer)(acc, el)
// =~= reducer( acc, foo(el))
=~= rc( rc( g(h(r))([], times2( 1)), 2), 3)
=~= rc( rc( filterReducer(isGreaterThanThree)(h(r))([] , times2( 1)),
2),
3)
// filterReducer(pred )(reducer)(acc, el)
// =~= pred(el) ? reducer( acc, el) : acc
=~= rc( rc( isGreaterThanThree( twice1) ? h(r)( [], twice1) : [],
2), /* where twice1 = times2(1)
h = mapReducer( add1) */
3)
=~= rc( rc( isGreaterThanThree( twice1) ? r([], add1(twice1)) : [],
2), /* where twice1 = times2(1)
r = concatReducer */
3)
=~= rc( rc( isGreaterThanThree( twice1) ? [].concat(add1(twice1)) : [],
2), /* where twice1 = times2(1) */
3)
=~= ...
mapping(foo)( filtering(pred)(reducer) )( acc, elt)
----------------------------------------( )
=~=
filtering(pred)(reducer)( acc, foo(elt) )
=~=
pred( foo(elt) ) ? reducer( acc, foo(elt) ) : acc