首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >组合函数的执行顺序

组合函数的执行顺序
EN

Stack Overflow用户
提问于 2017-11-27 08:39:21
回答 1查看 49关注 0票数 3

我一直在阅读关于传感器的知识,并尝试着理解这个概念。我现在对它们有了一点了解,但在我拉小提琴的过程中,我遇到了一些非常奇怪的事情,让我目瞪口呆。我希望有人能解释一下我错过了什么。

我有两个传感器,它们的签名是:reducer -> reducer

我还有一个简单的组合函数:const compose = (f, g) => x => f(g(x))

当我合成两个传感器时:

代码语言:javascript
复制
const filterLessThanThreeAndMultiply = compose(
  filteringReducer(lessThanThreePredicate),
  mappingReducer(multiplyTransform)
)

我希望评估是从右到左的,在这种情况下,在过滤之前应用映射转换。相反,首先应用过滤(这会给出预期的答案)。

但是f( g(x) )运行g(X)的结果的f,所以我的结果应该反映:

代码语言:javascript
复制
filteringReducer(lessThanThreePredicate)(mappingReducer(multiplyTransform)
(concatTransducer))

但相反,它反映(正确地):

代码语言:javascript
复制
mappingReducer(multiplyTransform)(filteringReducer(lessThanThreePredicate)
(concatTransducer))

(参见下面的代码)

为什么??!!(我怀疑一旦有人向我解释这里发生了什么,我就会在理解上取得巨大的飞跃)。

代码语言:javascript
复制
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]
EN

回答 1

Stack Overflow用户

发布于 2020-05-23 08:33:53

您可以看到filter发生在map之前(正确地),即使它们都在compose中,因为转换器的实现细节。我将通过在实现中分解传感器,然后向您展示如何使用它们来解释。

考虑mapfilter的以下变体

代码语言:javascript
复制
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

  1. mapArray接受一个函数element.
  2. filterArray和一个数组,并返回另一个对每个fn
  3. mapReducer应用了fn的数组;接受一个函数fn和一个数组,并返回由reducer => (y, xi) => {...}

过滤的另一个数组;获取一个函数fn并返回reducer => (y, xi) => {...}

  • filterReducer;获取一个函数fn并返回fn

现在,考虑换能器签名

reducer传感器具有以下特征: reducer ->

由于(y, xi) => {...}只是另一个reducer,这意味着mapReducer(multiplyTransform)filterReducer(lessThanThreePredicate)都是transducers.

太棒了!现在我们知道了什么是传感器,但是我们如何使用它们呢?

附件A(无作曲)

代码语言:javascript
复制
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]

为了设置我们的换能器,我们首先过滤x => x < 3,然后映射x => x * 100,我们必须像上面那样组成换能器lessThanThreeTransducerx100Transducer。现在,如果我们抛出compose,你将会得到为什么一切似乎都是倒退的答案。

附件B(包含compose)

代码语言:javascript
复制
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]

实际上,finalComposedReducerfinalReducerLessThanThreeThenX100ThenConcat在算法上是等价的。那么,

为什么??!!

这是传感器的实现细节。如果你仍然对传感器感兴趣,我在here上写了更多关于它们的文章。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47502557

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档