0.前言
函数式编程拥有更好的,组合性,灵活性,容错性,相比面向对象编程。
函数式编程入门,需理解“纯函数”,“柯里化”,“函数组合”这三个概念。
PS:本篇文章的案例使用ramdajs工具库。
1.纯函数
什么是纯函数?
相同输入,相同输出,无副作用。
什么是副作用?请看例子。
demo 1-0:
var array1 = [1,2,3,4,5];
var array2 = [1,2,3,5,5];
// 纯函数,它没有改变array1数组
array1.slice(0,3);
//=> [1,2,3]
array1
//=> [1,2,3,5,5]
// 非纯函数,副作用是改变了array2数组
array2.splice(0,3);
//=> [1,2,3]
array2
//=> [4,5]
demo 1-1:
// 纯函数
var checkAge = function(number) {
var innerVariable = 12;
return number >= innerVariable;
};
// 非纯函数,依赖外部变量。因为外部变量不可控,所以副作用是函数返回的值不可控。
var externalVariable = 12;
var checkNumber = function(number) {
return number >= externalVariable;
};
checkNumber(18);
//=> true
externalVariable = 20;
checkNumber(18);
//=> false
2.柯里化
没有你之前,无可厚非;有了你之后,不可或缺。
你就是柯里化。
那么什么是柯里化?
传给一个函数部分参数,返回一个函数去处理剩余参数。
当然,被柯里化的函数,都是纯函数。
具体理解,请看例子。
demo 2-0
var R = require('ramda');
var minus = function(a, b){ return a- b };
var curryMinus = R.curry( minus );
// R.__是参数占位符
var minus5 = curryMinus( R.__, 5 );
minus5(33);
//=> 28
var minus5Second =curryMinus(5, R.__);
minus5Second(33);
//=> -28
柯里化是函数组合的基础。因为它能保留任何参数的位置。
3.函数组合
相比面向对象的复用,需涉及到类继承的重构,虚方法,重写方法,甚至是抽象类,接口实现等概念,
函数式编程的函数组合概念,则更加自然易懂。
请看例子。
demo 3-0
var R = require('ramda');
var add = R.curry(function (a, b) {
return a + b;
});
var subtract = R.curry(function(a, b){
return a - b;
});
// 如果你没有传入参数占位符,缺省选中第一个参数
var add9 = add(9);
var subtract1 = subtract(1, R.__);
// 33这个值先经过subtract1运算,再经过add9运算,从右往左。
var result = R.compose(add9, subtract1);
result(33);
//=> 41
告一段落
在这里,我们已经知道函数式语言的三个基本概念纯函数,柯里化,函数组合。
并且可以运用函数组合,建一个纯函数组成的河流,让数据流动。
但编程里面还有控制流(control flow)、异常处理(error handling)这些概念,
以后有空写续集。
我认为,函数式语言的美妙之处是可以更加清晰地描述事物,相比自然语言。