函数式编程之高阶函数

173 阅读2分钟

函数式编程的核心思想就是尽量控制输入减少副作用。将复杂功能一个一个剥离成实现单个简单功能的纯函数,然后组合成新的函数用以实现一个复杂功能。

副作用

在函数式编程中对结果的各种干扰称为副作用(effect)。我们知道函数由输入,算法和输出组成。能够影响结果就是输入值(实参),除了输入值其他影响函数结构的外部因素就叫做副作用。 函数中常见的副作用:

  • 全局变量
  • IO影响,也就是浏览器中的用户行为
  • 网络请求

减少副作用的关键:纯函数和不可变

纯函数

纯函数指的是一个函数的变化只依赖其参数,在执行过程中没有副作用。它意味着相同的输入,永远会得到相同的输出。 下面列举了数组中一些常见的纯函数方法:

slice,concat,map,filter,reduce,reduceRight

部分应用和函数柯里化

柯里化就是把一个多元函数转换成一个一次调用的单元函数。核心就是上一个函数的运行结构刚好作为下一个函数的输入。

部分应用和柯里化很容易混淆,但是部分应用强调的是固定一定的参数,返回一个更小的单元而柯里化强调单元函数。

//柯里化
f(a,b,c)==>f(a)(b)(c)
//部分应用
f(a,b,c)==>f(a,b)(c)
  • 高级柯里化

通常我们不会自己写柯里化函数(curry),有很多库提供了curry函数的实现。

//在这个例子中当你传入的参数个数满足了函数的参数条件,就会返回值,而当你传入的参数个数不满足条件就会返回函数
const add=R.curry((x,y,z)=>x+y+z);
const add=add(1,2)(7)//10
const add1=add(1,2)//function

组合、管道和reduce

前面说的柯里化和部分应用函数构成了一个个的加工站,接下来为了组成流水线就需要组合、管道。

  • compose:可以将多个纯函数组成一条流水线。从右往左
const compose=(f,g)=>x=>f(g(x))
const f=x=>x+1;
const g=y=>y*2;
const fg=compose(f,g)//compose的顺序先计算g,再计算f
fg(1)//3

//同时compose是满足结合律的
compose(f,compose(g,t))=compose(compose(f,g),t)=f(g(t()))

//compose的实现
const compose=(...fns)=>(...args)=>fns.reduceRight((val.fn)=>fn.apply(null,[].concat(val)),args)
  • pipe:管道的功能和compose一样,只是执行顺序上有区别。从左往右

  • reduce

Ramda库

组合函数的debug

遇到函数出错时,我们要捕获哪个函数产生了错误可以使用trace。用来输出当前阶段的结果。

const lastUppder=compose(toUpperCase,head,trace('after reverse'),reverse)