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

  函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),并且λ演算的函数能够接受函数看成输入(参数)和输出(返回值)。和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。和过程化编程相比,函数式编程里函数的计算可随时调用。编程

  最近一直在研究函数式编程,从函数式编程中仿佛看到了js规范化的影子。你们都知道js是一门很灵活的编程语言,而这种灵活性在代码量的累积下会产生质量和可控性的问题。初学js的朋友大多都是结果导向,写的代码刚刚够用现有的项目,很难修改与扩展代码,并且不规范的代码经常让队友甚至是本身头疼。而函数式编程却能改变这样的现状。数组

  再说函数式编程以前按照惯例要说一些相关的知识。缓存

1.什么是纯函数?

  纯函数顾名思义就是很纯的函数,你们都喜欢纯粹的事物,那什么样的函数才配称做纯函数呢?
  简单地说,纯函数就是传入相同的参数能够返回相同的值的函数,也就是说返回的结果只依赖于传递的参数,而和环境没有关系。相似于咱们数学中的函数的概念。dom

Array.prototype.map()
Array.prototype.slice()
String.prototype.toUpperCase()

  像上面这样的函数就是纯函数编程语言

Array.prototype.sort()
Math.random()

  像上面这样的函数就不是纯函数了
  纯函数有不少优秀的性质让咱们喜欢,ide

1.纯洁性

  她既不会被环境改变也不会改变环境,结果只依赖传入值。那么这就方便咱们对函数进行缓存。下面以求x的平方为例(这里用到了ramda函数库,没接触也不要紧,这里只是讲概念,以后咱们会说起这个函数库)函数式编程

let square = R.memoizeWith(R.identity, x => x * x);
square(3); // => 9 第一次会调用原始方法并将参数和结果以key-value的形式存储。
square(3); // => 9 这里是调用缓存
square(3); // => 9 这里也是调用缓存

2.易测试性

  因为纯函数执行不须要环境,因此进行测试时咱们只须要面对函数自己测试就能够了。这让函数测试变得很是简单函数

3.透明性

  若是一段代码能够替换成它执行所得的结果,并且是在不改变整个程序行为的前提下替换的,那么咱们就说这段代码是引用透明的。因为纯函数老是可以根据相同的输入返回相同的输出,因此它们就可以保证老是返回同一个结果,这也就保证了引用透明性。测试

2.什么是柯里化?

  函数柯里化(curry)的定义很简单:传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。下面咱们对比一下柯里化以前的函数和柯里化的函数。spa

let add = (x, y, z) => x + y + z;
add(1,2,3) // => 6;
let add = (x, y, z) => {
  return z => {
    return y => {
      return x + y + z;
    }
  }
}
add(1)(2)(3) // => 6;

  后者就是柯里化的函数,它利用了函数的记忆性记住了每次传你进去的参数并返回了可继续执行的函数。是否是感受发现了新大陆?

3.什么是函数组合

  函数组合(compose)就是把多个纯函数组合起来解决函数嵌套问题。下面咱们来看两个例子

let compose = (f, g, h) => x => f(g(h(x)));
let add = x => x + 4;
let mul = x => x * 2;
let mis = x => x - 1;
compose(add, mul, mis)(1) // => 3
let compose = (f, g, h) => x => f(g(h(x)));
let getFirst = arr => arr[0];
let getUpperCase = str => str.toUpperCase();
let getReverse = arr => arr.reverse();
compose(getUpperCase, getFirst, getReverse)(['v', 'a', 'd', 'i', 'm']); // => 'M'

  由于纯函数的纯洁性,咱们能够把多个函数组合起来,注意必定是纯函数。

4.什么是point-free

point-free简单地说就是无需使用所要处理的值,只关注运算过程。能够用公式 fn = R.pipe(f1, f2, f3);表示,也就是说若是事先定义了函数f1,f2,f3就能够推算出函数fn,所以无需使用参数形式,下面咱们来对比一下两种形式。

let noPointFree = word => word.toUpperCase().split('-');
let pointFree = compose(split('-'),toUpperCase);

  pointfree 模式可以帮助咱们减小没必要要(中间变量)的命名,让代码保持简洁和通用。

  关于函数式编程先讲一下基础的知识,下一节我来说一下js函数式编程优秀的函数库----Ramda函数库。

 

原创博客:转载请注明从函数式编程到Ramda函数库(一)

相关文章
相关标签/搜索