函数式编程中有一种模式是通过组合多个函数的功能来实现一个组合函数。一般支持函数式编程的工具库都实现了这种模式,这种模式一般被称作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)) // 7
console.log(fun2(-2, 3)) // 9

从上面的例子可以看出,假设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())
}

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

// 结合律(associativity)
var associative = compose(f, compose(g, h)) == compose(compose(f , g), h); // true

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

函数式编程-compose与pipe的更多相关文章

  1. angular2系列教程(六)两种pipe:函数式编程与面向对象编程

    今天,我们要讲的是angualr2的pipe这个知识点. 例子

  2. [学习笔记]JavaScript之函数式编程

    欢迎指导与讨论:) 前言 函数式编程能使我们的代码结构变得简洁,让代码更接近于自然语言,易于理解. 一.减少不必要的函数嵌套代码 (1)当存在函数嵌套时,若内层函数的参数与外层函数的参数一致时,可以这 ...

  3. (转)现代C++函数式编程

    本文转自:http://geek.csdn.net/news/detail/96636     现代C++函数式编程 C++ 函数式编程 pipeline 开发经验 柯里化 阅读2127    作者简 ...

  4. 翻译连载 | 第 11 章:融会贯通 -《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

  5. 翻译连载 | 附录 A:Transducing(上)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

  6. 从函数式编程到Ramda函数库(一)

    函数式编程是种编程方式,它将电脑运算视为函数的计算.函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值).和指令式编程相比, ...

  7. python 函数式编程学习笔记

    函数基础 一个函数就是将一些语句集合在一起的部件,它们能够不止一次地在程序中运行.函数的主要作用: 最大化的代码重用和最小化代码冗余 流程的分解 一般地,函数讲的流程是:告诉你怎样去做某事,而不是让你 ...

  8. 给 JavaScript 开发者讲讲函数式编程

    本文译自:Functional Programming for JavaScript People 和大多数人一样,我在几个月前听到了很多关于函数式编程的东西,不过并没有更深入的了解.于我而言,可能只 ...

  9. JavaScript ES6函数式编程(二):柯里化、偏应用和组合、管道

    上一篇介绍了闭包和高阶函数,这是函数式编程的基础核心.这一篇来看看高阶函数的实战场景. 首先强调两点: 注意闭包的生成位置,清楚作用域链,知道闭包生成后缓存了哪些变量 高阶函数思想:以变量作用域作为根 ...

随机推荐

  1. POJ2960 S-Nim 【博弈论】

    Description Arthur and his sister Caroll have been playing a game called Nim for some time now. Nim ...

  2. 使用VLC Activex插件做网页版视频播放器

    网上找的一个小例子,包括时长播放时间等等都有. mrl可以设置本地文件,这样发布网站后只能播放本地有的文件, 如果视频文件全在服务器上,其他电脑想看的话,则可以IIS上发布个视频文件服务器,类似htt ...

  3. windows下连接smb服务器

    在运行里面输入:\\xxx.xxx.xxx.xxx   即可访问远程服务器

  4. URL存在跨站漏洞http host头攻击漏洞解决方案

    最近项目部署的时候客户使用的绿盟扫描出一些漏洞,老大让我处理,经过看大神的博客等方式,分享一些简单的解决方法. 一 跨网站脚本 跨网站脚本(Cross-site scripting,通常简称为XSS或 ...

  5. HBase读写的几种方式(二)spark篇

    1. HBase读写的方式概况 主要分为: 纯Java API读写HBase的方式: Spark读写HBase的方式: Flink读写HBase的方式: HBase通过Phoenix读写的方式: 第一 ...

  6. npm knowledge basics

    npm inro https://www.npmjs.com/ npm is the package manager for javascript npm 为 nodejs默认的包管理工具, 为nod ...

  7. Ubuntu16.04安装NVIDA驱动和CUDA

    该GPU是计算卡,不会用做显示,所以如果你希望自己的显示使用GPU,本方法可能失效. 服务器配置: CPU: E5-母鸡 GPU: NVIDIA  Tesla K40c 操作系统:Ubuntu 16. ...

  8. Java 集合系列08之 List总结

    一.List概述 1. List是一个接口,它继承于Collection接口,代表有序集合 2. ArrayList, LinkedList, Vector, Stack是List的4个实现类. Ar ...

  9. git add . 提示 `Changes not staged for commit`

  10. 第31月第15天 -fembed-bitcode

    1. 确保打包的时候使用的是fembed-bitcode, 而不是fembed-bitcode-maker fembed-bitcode-maker:只是简单的标记一下在archive出来的二进制中b ...