快速写curry函数和compose函数

我一直都把编程作为一项极其富有创造性和乐趣的工作,其意义就在于我们可以接触各种迷人而富有远见的编程思想,站在巨人的肩膀上眺望未来。

作为一名懒癌晚期编程工作者,任何可以让我少写代码的编程思想对我来说都是一种鸦片,代码本身就应当是简洁而美的,一个人写出来的代码,就是他的整个思想世界。

作为一名菜鸟,最近学习到函数式编程,立即就被这种声明示的编程模式吸引,实在没有更直白的编程方式了,这就是一个小孩或者天才应当使用的编程模式,像我这种半只脚步入中年的程序员,只能喟然嗟叹。

函数式编程应当有三个基石:纯函数,柯里化,组合化。

纯函数输出不被输入左右,自给自足,就像一截管道,放哪都能承上启下。

柯里化指对函数参数列表从左至右进一步拆分,把管道拆分成管环,所有管环拼接到一起才有结果流出:

  const pipe = (a,b,c) => a+b+c;

  const rings = curry(pipe);

  const ring_a = rings( 'a' );

  const ring_ab = rings( 'a' , 'b' ); // 和 rings( 'a' )( 'b' ) 等价,缺少最后的管环

  const ring_abc = rings( 'a' , 'b' , 'c' ); // 和 ring_ab( 'c' ) 等价,完成有输出 'abc'

上边的curry函数如果要从别的库引入,个人认为是不保险的,首先不能保证它是否引入多余的代码或者不符合使用场景的需求,自己造出来的轮子,出问题可以自己处理,修复别人的轮子会浪费大量时间。前段时间我就因为偷懒,用了mint-ui的一个组件,结果h5页面在oppo上出现重复点击出现位移的bug,花了半天看它的源码才找到问题所在。

下面是我自己实现的curry,比较简陋,但是能用:

  const curry = ( f,length ) => { length = length || f.length ; return (...usedArgs) => length - usedArgs.length > 0 ? curry( (...restArgs) => f.call(this,...usedArgs,...restArgs), length - usedArgs.length) : f.apply(this,usedArgs)}

组合化指将不同的管道拼接起来,前一个纯函数的流出流入下一个管道,顺理成章。需要注意的是这里管道的拼接顺序是从右至左的,按理说也应该是从左至右流通,不过可能是函数的参数写在函数名右边的原因,compose比curry好实现:

  const compose = (...functions) => flowIn => functions.reduceRight( ( acc,f ) => f(acc), flowIn )

最后利用curry和compose函数可以自己拼接管道,实现各种功能:

  const pipe1 = curry( (x,y)  => x + y)

  const pipe2 = x => x * x

  const pipes = compose( pipe2 , pipe1(2) )

  pipes( 1 ) // 9

猜你喜欢

转载自www.cnblogs.com/lowki/p/10853244.html