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

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

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

1.什么是纯函数?

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

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

  像上面这样的函数就是纯函数

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

  像上面这样的函数就不是纯函数了
  纯函数有很多优秀的性质让我们喜欢,

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)的定义很简单:传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。下面我们对比一下柯里化之前的函数和柯里化的函数。

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函数库(一)

从函数式编程到Ramda函数库(一)的更多相关文章

  1. 从函数式编程到Ramda函数库(二)

    Ramda 基本的数据结构都是原生 JavaScript 对象,我们常用的集合是 JavaScript 的数组.Ramda 还保留了许多其他原生 JavaScript 特性,例如,函数是具有属性的对象 ...

  2. 【Python】[函数式编程]高阶函数,返回函数,装饰器,偏函数

    函数式编程高阶函数 就是把函数作为参数的函数,这种抽象的编程方式就是函数式编程.--- - -跳过,不是很理解,汗 - ---

  3. Python之路(第七篇)Python作用域、匿名函数、函数式编程、map函数、filter函数、reduce函数

    一.作用域 return 可以返回任意值例子 def test1(): print("test1") def test(): print("test") ret ...

  4. python函数式编程之返回函数、匿名函数、装饰器、偏函数学习

    python函数式编程之返回函数 高阶函数处理可以接受函数作为参数外,还可以把函数作为结果值返回. 函数作为返回值 def laxy_sum(*args): def sum(): ax = 0; fo ...

  5. Python之路Python作用域、匿名函数、函数式编程、map函数、filter函数、reduce函数

    Python之路Python作用域.匿名函数.函数式编程.map函数.filter函数.reduce函数 一.作用域 return 可以返回任意值例子 def test1(): print(" ...

  6. Learning Python 012 函数式编程 2 返回函数 匿名函数 装饰器 偏函数

    Python 函数式编程 2 返回函数 返回函数的意思就是:函数作为返回值.(高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回.) 举个例子:实现一个可变参数的求和. 正常的函数: de ...

  7. 跟着ALEX 学python day3集合 文件操作 函数和函数式编程 内置函数

    声明 : 文档内容学习于 http://www.cnblogs.com/xiaozhiqi/  一. 集合 集合是一个无序的,不重复的数据组合,主要作用如下 1.去重 把一个列表变成集合 ,就自动去重 ...

  8. 理解函数式编程中的函数组合--Monoids(二)

    使用函数式语言来建立领域模型--类型组合 理解函数式编程语言中的组合--前言(一) 理解函数式编程中的函数组合--Monoids(二) 继上篇文章引出<范畴论>之后,我准备通过几篇文章,来 ...

  9. JavaScript函数式编程(纯函数、柯里化以及组合函数)

    JavaScript函数式编程(纯函数.柯里化以及组合函数) 前言 函数式编程(Functional Programming),又称为泛函编程,是一种编程范式.早在很久以前就提出了函数式编程这个概念了 ...

随机推荐

  1. PHP array_combine()

    // 需要替换 key 的数组 $arr_old = array( '0' => array('id' => 1, 'name' => 'Carroll'), '1' => a ...

  2. WPA2-PSK无线密码破解

    无线网络WIFI(wireless Fidelity )正确发音 /wai fai/ 是一个建立在IEEE 802.11标准的无线局域网,目前主流的无线上网模式主要有两种分别是 GRPS(手机无线上网 ...

  3. zoj3471 状态压缩dp基础

    /* dp[S]表示状态S下的最大收益,0表示没有了,1表示还在 */ #include<bits/stdc++.h> using namespace std; <<],mp[ ...

  4. C++ GetModuleFileName()

    关于GetModuleFileName function,参考:https://msdn.microsoft.com/en-us/library/windows/desktop/ms683197(v= ...

  5. ajax请求数据时什么时候用GET,什么时候用POST

    GET的目的就如同其名字一样是用于获取信息的.它旨在显示出页面上你要阅读的信息.浏览器会缓冲GET请求的执行结果,如果同样的GET请求再次发出,浏览器就会显示缓冲的结果而不是重新运行整个请求.重新请求 ...

  6. Python-数据类型之数字

    一:数字类型概述 数字提供了标量存储和直接访问,属于不可变数据类型,所谓不可变,我们可以认为,更改数字的值会生成一个新的对象 # id可以唯一表示一个对象 age =18 print(id(age)) ...

  7. js里添加的标签

    js里添加的标签.网页加载此标签绑定的js函数时,由于没有标签,故无法执行函数. 例如: js中添加了一个button: html1 += "<td><button typ ...

  8. 20165206 2017-2018-2 《Java程序设计》第6周学习总结

    20165206 2017-2018-2 <Java程序设计>第6周学习总结 教材学习内容总结 String类:可以被直接使用,不可以有子类. String对象:可以使用String类声明 ...

  9. 在Ubuntu内制作自己的VOC数据集

    一.VOC数据集的简介 PASCAL VOC为图像的识别和分类提供了一整套标准化的优秀数据集,基本上就是目标检测数据集的模板.现在有VOC2007,VOC2012.主要有20个类.而现在主要的模型评估 ...

  10. pycaffe简明文档

    pycaffe简明文档 by ChrisZZ, imzhuo@foxmail.com 2018年01月18日19:00:56 说明 caffe的python接口没有官方说明文档,例如查看一个函数的用法 ...