ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【函数】compose 函数和 pipe 函数

2020-05-31 21:03:28  阅读:256  来源: 互联网

标签:10 compose 函数 pipe add let multiply


目录:

1、compose 函数

2、pipe 函数

 

compose 函数

  compose 函数将需要嵌套执行的函数平铺。嵌套执行指的是,一个函数的返回值作为另一个函数的参数。

  其实 compose 函数在函数式编程中通常用来将几个有特点的函数拼凑在一起,让他们结合,产生一个崭新的函数。compose 函数的作用是实现函数式编程的 Pointfree, 使我们专注于转换而不是数据。也就是说,我们完全可以把数据处理的过程定义成一种与参数无关的合成运算,不需要用到代表数据的那个参数,只要把一些简单的运算步骤合成在一起即可,而 Pointfree 指的是不使用所要处理的值,只合成运算过程,即我们所指的无参数分隔。

  现在有这么一个需求,计算一个数,加上 10,再乘以 10的值。可能有人会这么做:

1 let calculate = x => ( x + 10 ) *10;
2 console.log( calculate( 10 ) );     //输出:200

  上面,这样写是没有问题的,但是这是命令式编程,这样的代码完全不具备复用性。作为一个函数式开发者,会对这段代码进行抽象来实现简化代码的目的,而且,函数式编程就是将程序分解为一些更可重用、更可靠、更易于理解的部分,然后再将它们组合起来形成一个更易于推理的程序整体。

  以上面的需求为例,我们关注的是它的动作,先加上 10, 再乘以 10。可以像下面这样做:

1 let add = x => x + 10;
2 let multiply = y => y * 10;
3 console.log( multiply(add(10)) );   //输出:200

  上面,将 add 函数的执行结果作为 multiply 的参数,这样也能实现需求。但是根据复合函数的定义,需要将代表两个动作的函数合成一个函数。分析 2 个函数的特性,第一,是两个函数都有一个共同的参数,第二,是函数的执行的顺序是从右到左,第三,是前面函数的结果将由后面的函数处理,根据特性,可以这样实现:

1 let add = x => x + 10;
2 let multiply = y => y * 10;
3 let compose = (f, g) => {
4     return function(x){
5         return f(g(x));
6     }
7 }
8 let calculate = compose( multiply, add );
9 console.log( calculate(10) );   //输出:200

  上面,使用了闭包来实现。首先,定义一个 compose 函数,接收 2 个函数作为参数。这个 compose 函数返回一个匿名函数,这个匿名函数接收 1 个参数,而且这个匿名函数将 2 个函数执行的结果返回。当调用的时候,只需要将 2 个函数作为参数传入。注意,根据函数调用的顺序,这里的执行动作是从右往左,即先执行 add ,再执行 multiply。

  这样的 compose 函数没有通用性,因为它只可以处理 2 个函数,接下来实现通用的 compose 函数:

 1 let add = x => x + 10;
 2 let multiply = y => y * 10;
 3 let compose = function(){
 4     let args = [].slice.call( arguments );
 5     return function( x ){
 6         return args.reduceRight( function (res, cb) {
 7             return cb(res);
 8         }, x)
 9     }
10 }
11 let calculate = compose( multiply, add );
12 console.log( calculate(10) );   //输出:200

  上面,通用的 compose 函数要做的第一件事是将传入的函数作为参数收集起来,所以这里将 arguments 转换为数组,因为需要把上一次执行结果当作参数传给下一次执行,所以可以使用 reduce() 来实现,reduce方法可以接收一个函数作为累加器,也就是说 reduce() 会将数组中的每一个元素依次执行传入的函数。同时要注意,复合函数执行的顺序是自右向左依次执行,而 reduce() 是从左往右开始累加,reduceRight() 是从右往左开始累加,所以这里用 reduceRight()。调用 compose 函数的执行顺序依然是从右往左执行。

  可以使用更简洁的 es6 语法实现 compose 函数,如下:

1 let add = x => x + 10;
2 let multiply = y => y * 10;
3 //es6 写法
4 const compose = (...args) => x => args.reduceRight( (res, cb ) => cb(res), x);
5 let calculate = compose( multiply, add );
6 console.log( calculate(10) );   //输出:200

  其实原理都是将传入的函数收集,唯一要注意的是:compose 执行方向是从右往左执行,所以要使用 reduceRight() 。通过 compose,在开发中可以去设计和抽象功能到具体的函数里面,以便后期的复用。而且更多的时候,compose 函数的存在其实是服务中间件的,redux 中间件就是通过 compose 来实现的。webpack loader 的加载顺序也是从右往左的,这是因为 webpack 选择了 compose 方式去实现。

 

pipe 函数

   compose 和 pipe 都是函数组合,组合是函数式编程非常重要的思想,其实,就是将多个函数组合在一起,以便能够构建出一个新函数。在函数式编程中,纯函数应该被设计为只做一件事,如果想实现多个功能,可以通过函数的组合来实现。

  pipe 函数是 compose 函数的复制品,唯一修改的是数据流方向,pipe 函数和 compose 函数做的事情相同,只不过交换了数据流方向,也就是说,compose 函数数据流的方向是从右向左,最右侧的函数会首先执行,之后数据传递给下一个函数,以此类推,一直到最左侧的函数最后执行。而 pipe 函数正好相反。

 

标签:10,compose,函数,pipe,add,let,multiply
来源: https://www.cnblogs.com/xiaoxuStudy/p/12602865.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有