compose

作者: LynnicKwan | 来源:发表于2019-06-30 23:06 被阅读0次

    compose是函数式编程中使用较多的一种写法, 它把逻辑解耦在各个函数中,通过compose的方式组合函数, 将外部数据依次通过各个函数的加工,生成结果。
    最简单例子

    f(x) = (5 + x) ^3
    这个运算有两个操作,先做加法运算,再做幂运算
    
    function power(x) {
      return Math.pow(x, 10)
    }
    function add(x) {
      return x + 5
    }
    function compose(fn1, fn2) {
        return function(x) {
          return fn1(fn2(x))
       }
    }
    // 可简写成
    const compose = (fn1, fn2) => x => fn1(fn2(x))
    compose(power,  add)(5)  // 1000
    

    这是两个函数compose的实现方式
    如果有N个函数呢,难道每次要写成

    const compose = (fn1, ..., fnn) => x => fn1(...(fnn(x)))
    

    如果N是100呢?
    我们仔细思考一下,把N个输入收敛成一个结果,是不是很像js的某个API?就是Array.prototype.reduce方法

    这个方法会对数组中的每个元素执行一个由你提供的reducer函数(升序执行),将其结果汇总为单个返回值。

    那么给定一个[fn1, fn2, ..., fnn]的数组funcs,如何实现函数组合的形式呢?
    根据reduce的定义,似乎只要实现reducer方法就行

    const reducer =  (accumulator, currentvalue) => {
        return (x) => {
            accumulator(currentvalue(x))
        }
    }
    // 简写
    const reducer = (acc, cur) =>  x => acc(cur(x))
    const compose = func.reduce(reducer)
    

    让我们做一个验证

    callback accumulator currentvalue 返回值
    round1 fn1 fn2 x => fn1(fn2(x))
    round2 x => fn1(fn2(x)) fn3 x =>((x) => fn1(fn2(x)))(fn3(x))

    因为reduce函数没有初始值,所以第一轮accumular将会是fn1, currrentvalue将会是fn2(见MDN中有无初始值时reduce的行为)。在第二轮中,累计值accumulator将会变成上一轮的返回值,执行reducer回调之后,会生成x =>((x) => fn1(fn2(x)))(fn3(x))
    这时候令我们费解的是,如果只有funcs = [fn1, fn2, fn3],这时候实际上reduce已经结束执行了,它的返回值怎么一点也不像我们期待的x => fn1(fn2(fn3(x))) 这种形式?
    实际上表格中第二轮返回值里加粗部分是一个立即执行函数,而fn3(x)则是这个函数的参数,代入之后即可得x => fn1(fn2(fn3(x)))
    完整的表格应该是

    callback accumulator currentvalue 返回值
    round1 fn1 fn2 x => fn1(fn2(x))
    round2 x => fn1(fn2(x)) fn3 x => fn1(fn2(fn3(x)))
    round3 x => fn1(fn2(fn3(x))) fn4 x => fn1(fn2(fn3(fn4(x))))
    ...
    round n x=> fn1(fn2(...fn(n-1)(x))) fnn x=> fn1(fn2(...fnn(x)))

    这个方法就是redux 中间件中实现多个函数组合的方式,
    非常的简洁优美, 然而了损失一定的可读性,需要积累一些函数式编程的基础才能快速参透。

    相关文章

      网友评论

        本文标题:compose

        本文链接:https://www.haomeiwen.com/subject/ewricctx.html