函數式編程(Functional Programming)以前都只是據說過,沒有使用過所謂的函數式編程思想。不大理解這個概念。最近弄python的時候遇到了這個概念。html
函數式編程對應的是命令式編程(imperative programming)。咱們平時寫的程序大都屬於這種編程方式:若是a大於b,就執行這個操做,不然的話,就執行這樣的操做。咱們一直研究的面向對象的編程也即是屬於命令式編程的一種。python
函數式編程最重要的是一切都是函數。這裏的一切包括什麼?函數能夠是變量麼?能夠。函數能夠是返回值麼?能夠。linux
若是函數是變量,那麼這個把函數看成變量的函數就是高階函數。好比python中的這個函數:算法
#!/usr/bin/python #coding:utf-8 def g(f, a, b): return f(a, b) def add(a, b): return a + b val = g(add, 1, 2) print val
其中g這個函數它就是高階函數,他有一個參數爲f。shell
在python中,高階函數的表明就是map和reduce。好比能夠看下下面的例子:編程
#!/usr/bin/python #coding:utf-8 def f(a): return a * a def add(a, b): return a + b val1 = map(f, [1,2]) val2 = reduce(add, val1) print val2
在上面例子裏面,map和reduce都是高階函數,它們的第一個參數傳遞進去的是函數。可是固然上面的例子寫的有點low,一點都不python,通常來講,咱們使用匿名函數lambda來替換傳遞進來的參數。閉包
#!/usr/bin/python #coding:utf-8 val1 = map(lambda x: x*x, [1,2]) val2 = reduce(lambda x,y: x+y, val1) print val2
這裏引伸的匿名函數的意思就很明顯了。它就是函數的擴展。函數式編程
高階函數除了能夠接受函數做爲參數以外,還能夠把函數做爲返回值返回。函數
#!/usr/bin/python #coding:utf-8 def multi(a, b): def f(): return a * a + b * b return f val = multi(1, 2) print val()
把函數做爲返回值,上面的例子在multi的時候其實並無執行對應的計算,而是在print的時候才執行計算,這個是一種延遲行爲。咱們稱之爲惰性求職(lazy evaluation)。this
咱們看到,在multi函數定義的a和b這兩個局部變量,並不隨着multi調用而銷燬,在print這行,才具體執行的時候,a=1和b=2 還繼續存在着。這就是「閉包」的威力。
迴歸到函數式編程,雖說函數式編程是一種思惟,和語言無關。可是隻有實現了上述匿名函數,函數閉包等功能的語言纔有函數式編程的能力。它最本質的觀點是,全部的編程思想都是以函數爲基本思想。
首先,函數式編程認爲每一個函數都是封閉的,不依賴外部的數據,也不改變外部的數據。好比咱們經常使用的OO裏面的方法,函數式編程就以爲不合理。
class A { public $isAuth = true; public isAuth(){ return $this->isAuth; } }
這裏面的isAuth依賴外部的變量$isAuth,因此它是不符合函數式編程的函數封閉原理的。
其次,函數像變量同樣使用,這一點咱們上面的部分已經說明清楚了。常常說的一句話是,函數是一等公民。
好比像不少算法裏面使用的遞歸算法,就算是函數式思惟和非函數式思惟的區別。好比計算斐波那契數列,從函數式思惟開始思考,咱們很容易思考到遞歸算法。而從其它思惟出發,咱們經常考慮的就是非遞歸解法。
public static long fib(int n) { if(n <= 1) return n; else return fib(n-1) + fib(n-2); }
從這個例子咱們能夠看出,使用函數式思想的一個好處,很是符合咱們人類直觀的理解。咱們是要告訴程序要去作什麼,而不是怎麼去作。
https://www.zhihu.com/question/28292740
https://www.ibm.com/developerworks/cn/linux/l-cn-closure/index.html