我的以为这个定义肥肠生动形象了。
函数式编程到处体现着数学的逻辑思想,经过减小外部依赖来避免外部变量的改变对于程式内部状态的改变,使得程序变得简易、声明式、易于维护。
这里推荐一下F大的《JS函数式编程指南》,系统介绍了函数式编程的思想。
中文版电子书下载地址走你:https://llh911001.gitbooks.io...
本文章是本身阅读后的一些理解和记录~html
这个概念一样出于书中。规定了变量能够取的值得范围,以及该类型的值能够进行的操做。根据类型的值的可赋值情况,能够把类型分为三类。git
在scala中,函数是能够做为参数来传递而且返回的,因此scala中的函数就是first class function
PS:scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各类特性。
所以,function做为变量的一种,能够被储存,看成参数传递,或者被复制给变量等等...程序员
首先弄清纯函数的概念:Pure function
意指相同的輸入,永遠會获得相同的輸出,并且沒有任何顯著的反作用。
它符合两个条件:编程
简单来讲,也就是当一个函数的输出不受外部环境影响,同时也不影响外部环境时,该函数就是纯函数,也就是它只关注逻辑运算和数学运算,同一个输入总获得同一个输出。
好比slice
和splice
,可是slice
是纯函数,而splice
不是,由于后者会改变源数据。
这就是强调使用纯函数的缘由,由于纯函数相对于非纯函数来讲,在可缓存性、可移植性、可测试性以及并行计算方面都有着巨大的优点。数组
看一下书中的例子:缓存
// impure var minimum = 21; var checkAge = function(age) { return age >= minimum; }; // pure var checkAge = function(age) { var minimum = 21; return age >= minimum; };
在impure 的版本中,checkAge 的結果將取決於 minimum 這個变量,换句话说,除了输入之外,它将取决于系统状态,一旦引用了外部环境,它就不符合pure了。
固然,也能够直接冻结变量,使得状态再也不变化,那么它也是一个纯函数:less
var immutableState = Object.freeze({ minimum: 21, });
书中定义柯里化的概念是:你能够只透過部分的參數呼叫一個 function,它會回傳一個 function 去處理剩下的參數。
函数柯里化是一种“预加载”函数的能力,经过传递一到两个参数调用函数,就能获得一个记住了这些参数的新函数。从某种意义上来说,这是一种对参数的缓存,是一种很是高效的编写函数的方法,将一个低阶函数转换为高阶函数的过程就叫柯里化。编程语言
//举个栗子 var checkage = min => (age => age > min); var checkage18 = checkage(18); checkage18(20); // =>true var curry = require('lodash').curry; //柯里化两个纯函数 var match = curry((what, str) => str.match(what)); var filter = curry((f, ary) => ary.filter(f)); //判断字符串里有没有空格 var hasSpaces = match(/\s+/g); hasSpaces("hello world"); // [ ' ' ] hasSpaces("spaceless"); // null var findSpaces = filter(hasSpaces); findSpaces(["tori_spelling", "tori amos"]); // ["tori amos"]
假设要对某个字符串作一系列操做,咱们作的事情一多,嵌套的层数会很是深。相似于巢状堆积(好比c(b(a())))这种堆砌方式很是不直观,当咱们但愿代码以平行方式(书中成为左倾)组合执行时,就成为Compose
compose 的概念直接來自於數學課本,因此compose都有的一个特性:ide
// 結合律(associativity) var associative = compose(f, compose(g, h)) == compose(compose(f, g), h); // true
pointfree 模式指的是,永远没必要说出你的数据。它的意思是说,函数无须说起将要操做的数据是什么样的函数式编程
// 非 pointfree,因為我們提到資料:word var snakeCase = function(word) { return word.toLowerCase().replace(/\s+/ig, '_'); }; // pointfree var snakeCase = compose(replace(/\s+/ig, '_'), toLowerCase);
这种风格可以帮助咱们减小没必要要的命名,让代码保持简洁和通用。
固然,为了在一些函数中写出Point Free的风格,在代码的其它地方必然是不那么Point Free的,这个地方须要本身取舍。
// 命令式 var makes = []; for (var i = 0; i < cars.length; i++) { makes.push(cars[i].make); } // 宣告式 var makes = cars.map(function(car) { return car.make; });
命令式代码:命令“机器”如何去作事情(how),这样无论你想要的是什么(what),它都会按照你的命令实现。
声明式代码:告诉“机器”你想要的是什么(what),让机器想出如何去作(how)。
命令式的循环要求你必须先实例化一个数组,并且执行完这个实例化语句以后,解释器才继续执行后面的代码。而后再直接迭代 cars 列表,手动增长计数器,就像你开了一辆零部件所有暴露在外的汽车同样。这不是优雅的程序员应该作的。
声明式的写法是一个表达式,如何进行计数器迭代,返回的数组如何收集,这些细节都隐藏了起来。它指明的是作什么,而不是怎么作。除了更加清晰和简洁以外,map 函数还能够进一步独立优化,甚至用解释器内置的速度极快的 map 函数,这么一来咱们主要的业务代码就无须改动了