在维基百科中已经对函数式编程有了很详细的介绍。那我们就来摘取一下Wiki上对Functional Programming的定义In computer science,functional programmingis a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data.简单地翻译一下也就是说函数式编程是一种编程模型他将计算机运算看做是数学中函数的计算并且避免了状态以及变量的概念。接下来我们就来剖析下函数式编程的一些特征。3. 从并发说开来说来惭愧我第一个真正接触到函数式编程要追溯到两年以前的《Erlang程序设计》我们知道Erlang是一个支持高并发有着强大容错性的函数式编程语言。因为时间太久了而且一直没有过真正地应用所以对Erlang也只是停留在一些感性认识上。在我眼里Erlang对高并发的支持体现在两方面第一Erlang对轻量级进程的支持请注意此处进程并不等于操作系统的进程而只是Erlang内部的一个单位单元第二就是变量的不变性。4. 变量的不变性在《Erlang程序设计》一书中对变量的不变性是这样说的Erlang是目前唯一变量不变性的语言。具体的话我记不清了我不知道是老爷子就是这么写的还是译者的问题。我在给这本书写书评的时候吹毛求疵地说我对这句话有异议切不说曾经的Lisp再到如今的F#都对赋值操作另眼相看低人一等。单说如今的Java和C#提供的final和readonly一样可以支持变量的不变性而这个唯一未免显得有点太孤傲了些。让我们先来看两段程序首先是我们常见的一种包含赋值的程序class Account:def __init__(self,balance):self.balance balancedef desposit(self,amount):self.balance self.balance amountreturn self.balancedef despositTwice(self):self.balance self.balance * 2return self.balanceif __name__ __main__:account Account(100)print(account.desposit(10))print(account.despositTwice())这段程序本身是没有问题的但是我们考虑这样一种情况现在有多个进程在同时跑这一个程序那么程序就会被先desposit 还是先 despositTwice所影响。但是如果我们采用这样的方式def makeAccount(balance):global despositglobal despositTwicedef desposit(amount):result balance amountreturn resultdef despositTwice():result balance * 2return resultdef dispatch(method):return eval(method)return dispatchif __name__ __main__:handler makeAccount(100)print(handler(desposit)(10))print(handler(despositTwice)())这时我们就会发现无论多少个进程在跑因为我们本身没有赋值操作所以都不会影响到我们的最终结果。但是这样也像大家看到的一样采用这样的方式没有办法保持状态。这也就是我们在之前概念中看到的无状态性。5. 再看函数式编程的崛起既然已经看完了函数式编程的基本特征那就让我们来想想数十年后函数式编程再次崛起的幕后原因。一直以来作为函数式编程代表的Lisp还是Haskell更多地都是在大学中在实验室中应用而很少真的应用到真实的生产环境。先让我们再来回顾一下伟大的摩尔定律1、集成电路芯片上所集成的电路的数目每隔18个月就翻一番。2、微处理器的性能每隔18个月提高一倍而价格下降一半。3、用一个美元所能买到的电脑性能每隔18个月翻两番。一如摩尔的预测整个信息产业就这样飞速地向前发展着但是在近年我们却可以发现摩尔定律逐渐地失效了芯片上元件的尺寸是不可能无限地缩小的这就意味着芯片上所能集成的电子元件的数量一定会在某个时刻达到一个极限。那么当技术达到这个极限时我们又该如何适应日益增长的计算需求电子元件厂商给出了答案就是多核。多核并行程序设计就这样被推到了前线而命令式编程天生的缺陷却使并行编程模型变得非常复杂无论是信号量还是锁的概念都使程序员不堪其重。就这样函数式编程终于在数十年后终于走出实验室来到了真实的生产环境中无论是冷门的HaskellErlang还是ScalaF#都是函数式编程成功的典型。6. 函数式编程的第一型我们知道对象是面向对象的第一型那么函数式编程也是一样函数是函数式编程的第一型。我们在函数式编程中努力用函数来表达所有的概念完成所有的操作。在面向对象编程中我们把对象传来传去那在函数式编程中我们要做的是把函数传来传去而这个说成术语我们把他叫做高阶函数。那我们就来看一个高阶函数的应用熟悉js的同学应该对下面的代码很熟悉让哦我们来写一个在电子电路中常用的滤波器的示例代码。def Filt(arr,func):result []for item in arr:result.append(func(item))return resultdef MyFilter(ele):if ele 0 :return 0return eleif __name__ __main__:arr [-5,3,5,11,-45,32]print(%s % (Filt(arr,MyFilter)))哦之前忘记了说什么叫做高阶函数我们给出定义在数学和计算机科学中高阶函数是至少满足下列一个条件的函数:接受一个或多个函数作为输入输出一个函数那么毫无疑问上面的滤波器就是高阶函数的一种应用。在函数式编程中函数是基本单位是第一型他几乎被用作一切包括最简单的计算甚至连变量都被计算所取代。在函数式编程中变量只是一个名称而不是一个存储单元这是函数式编程与传统的命令式编程最典型的不同之处。让我们看看变量只是一个名称在上面的代码中我们可以这样重写主函数if __name__ __main__:arr [-5,3,5,11,-45,32]func MyFilterprint(%s % (Filt(arr,func)))当然我们还可以把程序更精简一些利用函数式编程中的利器map,filter和reduce :if __name__ __main__:arr [-5,3,5,11,-45,32]print(%s % (map(lambda x : 0 if x0 else x ,arr)))这样看上去是不是更赏心悦目呢这样我们就看到了函数是我们编程的基本单位。7. 函数式编程的数学本质忘了是谁说过一切问题归根结底到最后都是数学问题。编程从来都不是难事儿无非是细心加上一些函数类库的熟悉程度加上经验的堆积而真正困难的是如何把一个实际问题转换成一个数学模型。这也是为什么微软Google之类的公司重视算法这也是为什么数学建模大赛在大学计算机系如此被看重的原因。先假设我们已经凭借我们良好的数学思维和逻辑思维建立好了数学模型那么接下来要做的是如何把数学语言来表达成计算机能看懂的程序语言。这里我们再看在第四节中我们提到的赋值模型同一个函数同一个参数却会在不同的场景下计算出不同的结果这是在数学函数中完全不可能出现的情况f(x) y 那么这个函数无论在什么场景下都会得到同样的结果这个我们称之为函数的确定性。这也是赋值模型与数学模型的不兼容之处。而函数式编程取消了赋值模型则使数学模型与编程模型完美地达成了统一。8. 函数式编程的抽象本质相信每个程序员都对抽象这个概念不陌生。