什么是函数式编程
今天在逛微博看别人吐槽.Net
开源时发现他们除了说C#
,java
之外,还提及了Scala
.之前从来都没听说过这种语言,后来一查才发现这是一种学习坡度略陡的高逼格语言.
- Scala是
Scalable language(可灵活升级的语言)
的简写. - 是一种函数式和面向对象的混合语言.
- 既能拿来写脚本,也能胜任高并发大项目.
- 个人感觉语法类似
Python
等一系列语言,没有分号,靠缩进分块等. - 主要运行在JVM,也有.Net实现,不过用的少.
- 可调用所有java library, java也可以调用它的library,与java交互性强.
- 学习门槛高,但精通后编写程序的代码量可以少很多,比java之类的可以少一半左右.
- java可以开发的,scala都能开发.(所以说也可以用它来写Android).
- scale基本上无需定义数据类型,会进行自识别.
- ……
等等,我这篇blog应该是讲函数式编程
.上面的只是勾起大家对Scala的兴趣,关于Scala这门语言,我会在接下来的时间里边学习边总结.
什么是函数式编程
函数式编程是一种编程范式,是一类典型的编程风格,是用一系列嵌套的函数来代替运算过程,避免使用全局变量和状态. (想系统学习编程范式可以看斯坦福的一门高评价公开课:编程范式)
例如用熟悉的Android来解释:
//SQL查询语句的ActiveAndroid实现
//原生SQL语句为"SELECT * FROM USER WHERE age = 45"
Select().from(User.class).where("age = ?", user.getAge()).execute();
这就将一个SQL语句的直接运算替换成了一系列函数的嵌套.
这里由于函数式编程
是一种编程风格,所以说就算是面向对象编程语言
也是可以通过一定的方法来使用函数式编程
,这些没有绝对的界限,只是实现的难易程度不同而已.
函数式编程特点
1. 函数作为第一对象
在函数式编程中,函数是第一对象,类似于面向对象编程中的对象,他几乎被用作一切,包括最简单的计算,甚至连变量都被计算所取代,在函数间传递的不再是变量,而是一个个的函数。
var upCase = function(i){ i.toUpperCase(); };
['a','b','c'].forEach(upCase);
2. 引用的透明性
一切的运算都在函数中发生,同时每个函数都保持高度的独立性.由于避免全局变量和状态的使用,保证整个函数仅仅与传入的参数有关,传入相同的参数,结果永远都是一样的.
最好的例子就是使用递归,通过每次递归传入不同的参数来执行一系列的运算.整个递归过程除了传入参数外和返回值外,函数不会和外部有任何的交互.这样进一步对函数进行了解耦,体现出了`Scalable(灵活,可升级)`的特点.
函数式编程的好处
1. 代码简洁易读,开发效率高
函数式编程使得代码更加接近自然语言,如果说面向对象编程
是名词的聚会,函数式编程
则是动词+名词的天下.同时由于基本上全部被封装为独立模块的函数,使得代码的重用变多,代码量变少.
//用java创建map
Map<String, Integer> numberMap = new HashMap<String, Integer>();
numberMap.put("one", 1);
numberMap.put("two", 2);
numberMap.put("three", 3);
//用Scala创建map
var numberMap = Map("one" -> 1, "two" -> 2, "three" -> 3)
//1 + 2 + 3 * 4用一般编程方法写
var a = 1 + 2 + 3 * 4;
//或者
var a = 1;
var b = 1 + 2;
var c = 3;
var d = c * 4;
var e = b + d;
//而用函数式编程的话
function add(a, b){return a + b};
function multiply(a, b){return a * b};
add(add(1,2),multiply(3,4))
//或者更接近自然语言的
add(1,2).add(multiply(3,4))
2. 代码管理方便,健壮性强
由于使用了函数式编程这种高度封装的风格,每个函数都不互相依赖,都可以看做独立单元,有利于单元测试
,debug
和模块化组合
.
3. 为并发编程而生
先看个例子就能明白
var s1 = function F1();
var s2 = function F2();
var s3 = function F3(s2, s1);
由于不存在全局变量和状态,就算将s1, s2两个函数放入两个不同的线程中跑,无论哪个谁先执行,都不会影响到s3的结果,函数式编程根本就不需要考虑死锁
.