上一篇博客介紹了函數式編程中的基礎知識:html
1)什麼是編程範式;編程
2)編程函數與數學函數的關係。異步
上篇文章介紹了函數式編程屬於聲明式編程範式中的一種,它仿照數學概念中的公式演算去解決問題,是一種更接近數學語言的編程方式。而且咱們知道函數式編程中全部的函數都是「純函數(Pure Function)」,由於只有純函數才符合數學中對函數的定義,即:ide
1)函數均有輸入(均帶有參數)、均有輸出(函數有返回值);函數式編程
2)使用相同參數調用函數,獲得的返回值不管什麼時候均相等(不受其餘因素影響)。異步編程
數學函數中包含一類函數叫「高階函數」,它指「接收一個(多個)函數做爲輸入,或者返回一個函數」的函數。在函數式編程中,一樣存在這樣的高階函數。只要一個函數包含有一個(多個)函數做爲參數,或者返回另一個函數,那麼這個函數就稱爲「高階函數」。在.NET中咱們使用委託來封裝方法,這樣方法就能夠像普通類型同樣做爲程序之間傳遞的參數、返回值。在.NET中已經有不少場合使用委託做爲函數的參數,好比在異步編程時調用的一些方法均帶有AsyncCallback委託類型的參數(BeginInvoke等),尤爲是C#3.0出現以後,咱們在使用一些相似Select()、Where()等擴展方法時,這些方法均會包含一個委託類型的參數:函數
1 string[] names = { "abc", "def", "ghi", "jkl", "mno" }; 2 IEnumerable<string> query = names 3 .Where(n => n.Contains("a")) 4 .OrderBy(n => n.Length) 5 .Select(n => n.ToUpper()); 6 foreach (string name in query) Console.WriteLine(name);
注意上面代碼中使用Lambda表達式就是快速建立委託的一種方式。而且每一個委託的簽名幾乎都一致:包含輸入參數,有返回值。spa
到如今爲止,咱們不多碰到返回值是委託類型的函數。並非沒有這樣的函數,只能說C#在容納「函數式編程」的程度還不是很夠。咱們徹底能夠本身編寫一個返回委託類型的「高階函數」,好比數學中爲一個函數求導函數的過程:code
1 public delegate double Function1X(double x); //一元函數 2 public Function1X GetDerivative(Function1X func) //高階函數,函數做爲輸入、返回值 3 { 4 double deltaX = 0.00000001; 5 return x => (func(x+deltaX)-func(x))/deltaX; //導數定義(近似) 6 }
如上代碼所示,GetDerivative()方法包含一個委託類型參數,表明須要求導函數的函數;而且返回一個委託類型,表明求得的導函數。GetDerivative()方法既包含函數做爲參數,又能返回一個函數,所以它屬於「高階函數」。htm
總結:
1)在編程中,咱們可使用「純函數」來表明一個數學函數。「純函數」無反作用(Side-Effect),而且符合數學中對函數的定義。能夠這麼說,編程函數涵蓋的範圍包含數學函數;
2)若是一個純函數的參數又是一個函數,或者該純函數可以返回另外一個函數,那麼這個純函數就稱爲「高階函數」,它與數學中的高階函數對應。
到目前爲止,我所講到的全部內容都是爲了讓你在「程序」和「數學」之間找到一個共同點,可以一一類比。而這個過程當中,「純函數」無疑是重點。
下面分享一個demo,可以繪製任意給定函數的曲線圖,並可以繪製指定點(X)處的切線。demo中主要演示一個求導函數的高階函數和一個求切線函數的高階函數:
1 /// <summary> 2 /// 求導函數 近似 3 /// </summary> 4 /// <param name="func"></param> 5 /// <returns></returns> 6 private Function1X Get(Function1X func) 7 { 8 double delatX = 0.00000000001; 9 return x => (func(x + delatX) - func(x)) / delatX; 10 } 11 12 /// <summary> 13 /// 根據斜率和(x,y)獲得切線方程 14 /// </summary> 15 /// <param name="k"></param> 16 /// <param name="x"></param> 17 /// <param name="y"></param> 18 /// <returns></returns> 19 private Function1X Get2(double k, double x, double y) 20 { 21 // y = kx + b 22 // b = y - kx 23 double b = y - k * x; 24 return a => k * a + b; 25 }
(demo中解析函數表達式的過程使用到了老外的方法,站在巨人肩膀上:))下面是效果圖:
源碼下載地址:http://files.cnblogs.com/xiaozhi_5638/Functional_Program.rar