• 函数式编程-compose与pipe


    函数式编程中有一种模式是通过组合多个函数的功能来实现一个组合函数。一般支持函数式编程的工具库都实现了这种模式,这种模式一般被称作compose与pipe。以函数式著称的Ramda工具库为例。

    const R = require('ramda');
    function inc (num) {
      return ++num;
    }
    const fun1 = R.compose(Math.abs, inc, Math.pow)
    const fun2 = R.pipe(Math.pow, Math.abs, inc)
    console.log(fun1(-2, 3)) 
    console.log(fun2(-2, 3)) 
    

    从上面的例子可以看出,假设fgh分别表示三个函数,则compose(f,g,h)返回的函数完成类似(...args) => f(g(h(...args)))的功能。即从右到左组合多个函数,前面函数的返回值作为下一个函数的参数;pipe(f,g,h)返回的函数完成类似(...args) => h(g(f(...args)))的功能,即从左到右组合多个函数,前面函数的返回值作为下一个函数的参数;预计最先执行的函数可以接受任意个参数,后面的函数预计只接受一个参数。把compose放在前面讲是因为其更加体现了数学含义上的从右到左的操作。
    redux中即有使compose函数的应用来增强store

    import { createStore, applyMiddleware, compose } from 'redux'
    import thunk from 'redux-thunk'
    import DevTools from './containers/DevTools'
    import reducer from '../reducers'
    const store = createStore(
      reducer,
      compose(
        applyMiddleware(thunk),
        DevTools.instrument()
      )
    )
    

    总的来说,composepipe函数接收函数序列,并返回一个函数,使用数组的reduce方法可以很容易实现这两个函数,下面是redux源码中对compose方法的实现:

    function compose(...funcs) {
      if (funcs.length === 0) {
        return arg => arg
      }
    
      if (funcs.length === 1) {
        return funcs[0]
      }
    
      return funcs.reduce((a, b) => (...args) => a(b(...args)))
    }
    

    上面的代码是ES6+的实现方式,仿照上面的代码很容易写出ES5的实现方法

    function _compose(f, g) {
      return function() {
        return f.call(this, g.apply(this, arguments));
      };
    }
    
    function compose() {
      var args = Array.prototype.slice.call(arguments)
      if (args.length === 0) {
        return function(arg){
          return arg
        }
      }
      if (args.length === 1) {
        return args[0]
      }
      return args.reduce(_compose)
    }
    

    实现了compose方法,只需要改动很少的地方就能实现pipe方法。

    function pipe(...funcs) {
      if (funcs.length === 0) {
        return arg => arg
      }
    
      if (funcs.length === 1) {
        return funcs[0]
      }
    
      return funcs.reduce((a, b) => (...args) => b(a(...args)))
    }
    

    或者直接借助compose方法实现pipe

    function pipe(...funcs){
      if(funcs.length === 0) {
        return arg => arg
      }
      return compose(...funcs.reverse())
    }
    

    组合的概念来自于数学,其有一个重要的特性就是结合律

    
    var associative = compose(f, compose(g, h)) == compose(compose(f , g), h); 
    

    符合结合律意味着不管你是把g和 h分到一组,还是把fg分到一组都不重要。在实际开发过程中,我们可以尽可能的最小化函数的功能,这也符合单一原则,然后通过结合以及组合来完成较大的功能需求。

    https://www.cnblogs.com/star91/p/han-shu-shi-bian-chengcompose-yupipe.html

  • 相关阅读:
    圣诞节快乐 | 圣诞特效来了!!
    前端特效demo | 值得收藏的6个 HTML5 Canvas 实用案例
    前端特效demo | 一起围观 10 种创意时钟
    即学即用,轻松搞定这些选择器!(下)
    架构师究竟要不要写代码?
    偷懒秘诀之变量篇
    弹幕,是怎样练成的?
    [C++]模板类和模板函数
    [C++]typedef用法
    [面试]CVTE 2019提前批 Windows应用开发一面
  • 原文地址:https://www.cnblogs.com/feng9exe/p/11014972.html
Copyright © 2020-2023  润新知