函數式編程(2) 高階函數

  上一篇博客介紹了函數式編程中的基礎知識: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         }
View Code

(demo中解析函數表達式的過程使用到了老外的方法,站在巨人肩膀上:))下面是效果圖:

源碼下載地址:http://files.cnblogs.com/xiaozhi_5638/Functional_Program.rar

 

函數式編程(1)

相關文章
相關標籤/搜索