我一直在读传感器并试图掌握这个概念。我现在对它们了解了一点,但在我摆弄的过程中,我遇到了一些让我目瞪口呆的特别奇怪的东西。我希望有人可以解释我失踪的东西。
我有2个具有签名的传感器:reducer -> reducer
我还有一个简单的撰写函数:const compose = (f, g) => x => f(g(x))
当我组成2个传感器时:
const filterLessThanThreeAndMultiply = compose(
filteringReducer(lessThanThreePredicate),
mappingReducer(multiplyTransform)
)
我希望评估是从右到左,在这种情况下,在过滤之前应用映射变换。相反,首先应用过滤(这给出了预期的答案)。
但是f(g(x))运行g(x)的结果f,所以我的结果应该反映出来:
filteringReducer(lessThanThreePredicate)(mappingReducer(multiplyTransform)
(concatTransducer))
但它反映(正确):
mappingReducer(multiplyTransform)(filteringReducer(lessThanThreePredicate)
(concatTransducer))
(见下面的代码)
为什么?? !! (我怀疑,一旦有人向我解释这里发生的事情,我会在理解上有一个巨大的飞跃。)
const filteringReducer = predicate => transducer => (result, input) =>
predicate(input) ? transducer(result, input) : result
const mappingReducer = transform => transducer => (result, input) =>
transducer(result, transform(input))
const compose = (f, g) => x => f(g(x))
const concatTransducer = (a, b) => a.concat([b])
const lessThanThreePredicate = x => x < 3
const multiplyTransform = x => x * 100
const filterLessThanThreeAndMultiply = compose(
filteringReducer(lessThanThreePredicate),
mappingReducer(multiplyTransform)
)
const result = [-2, -1, 0, 1, 2, 3, 4].reduce(
filterLessThanThreeAndMultiply(concatTransducer),
[]
)
console.log('result ', result) // [-200, -100, 0, 100, 200]
答案 0 :(得分:0)
由于换能器的实现细节,即使filter
都在map
内,您仍看到compose
发生在map
之前。我将通过分解实现中的换能器,然后向您展示如何使用它们来进行解释。
请考虑以下filter
和const mapArray = fn => array => array.map(fn) // map for arrays
const filterArray = fn => array => array.filter(fn) // filter for arrays
const mapReducer = fn => reducer => (y, xi) => reducer(y, fn(xi)) // map for reducers
const filterReducer = fn => reducer => (y, xi) => fn(xi) ? reducer(y, xi) : y // filter for reducers
的变体
mapArray
fn
接受一个函数fn
和一个数组,并返回另一个将filterArray
应用于每个元素的数组。fn
接受一个函数fn
和一个数组,并返回由mapReducer
过滤的另一个数组fn
使用函数reducer => (y, xi) => {...}
并返回filterReducer
fn
使用函数reducer => (y, xi) => {...}
并返回(y, xi) => {...}
现在,考虑换能器签名
换能器具有签名:reducer-> reducer
给出mapReducer(multiplyTransform)
只是另一个简化器,这意味着filterReducer(lessThanThreePredicate)
和const x100Transducer = mapReducer(x => x * 100)
const lessThanThreeTransducer = filterReducer(x => x < 3)
const concat = (y, xi) => y.concat([xi])
const finalReducerLessThanThreeThenX100ThenConcat = (y, xi) => (
lessThanThreeTransducer( // this is called with (y, xi) first
x100Transducer( // then this
concat // finally this
)
)(y, xi)
)
[1, 2, 3, 4, 5].reduce(finalReducerX100ThenConcat, []) // => [100, 200]
都是换能器。
太好了!所以现在我们知道什么是换能器,但是我们如何使用它们呢?
展览A(无内容)
x => x < 3
为了设置传感器,以便我们首先过滤x => x * 100
然后映射lessThanThreeTransducer
,我们必须像上面所做的那样组成传感器x100Transducer
和compose
。现在,如果我们折腾const x100Transducer = mapReducer(x => x * 100)
const lessThanThreeTransducer = filterReducer(x => x < 3)
const concat = (y, xi) => y.concat([xi])
const compose = (f, g) => x => f(g(x)) // f is lessThanThreeTransducer, g is x100Transducer
// x is concat (compare to above)
const finalComposedReducer = compose(lessThanThreeTransducer, x100Transducer)(concat)
[1, 2, 3, 4, 5].reduce(finalComposedReducer, []) // => [100, 200]
,您将得到为什么一切看起来都倒退的答案。
展览B(含撰写)
finalComposedReducer
实际上,finalReducerLessThanThreeThenX100ThenConcat
和{{1}}在算法上是等效的。所以,
为什么?? !!
这是换能器的实现细节。如果您仍然对换能器感到好奇,请写更多关于换能器的here。