函數式編程-compose與pipe

函數式編程中有一種模式是經過組合多個函數的功能來實現一個組合函數。通常支持函數式編程的工具庫都實現了這種模式,這種模式通常被稱做compose與pipe。以函數式著稱的Ramda工具庫爲例。html

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方法的實現:redux

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方法。app

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.htmlui

相關文章
相關標籤/搜索