在函數式編程中,可以把函數看作數據。函數也可以作為參數,函數還可以返回函數。比如,LINQ就是基於函數式編程的。
語句式編程可能這樣寫:
string result; if(value > 0) { result = "正數"; } else { result = "負數"; }
而使用函數式表達式,可以簡化為:
var result = value > 0 "正數":"負數";
再來看一個過濾和排序的例子:
var i = 0; while(i < list.Count) { if(list[i] % 2 != 0) { list.RemoveAt(i); } else { ++i; } } list.Sort();
函數式編程可以寫成如下:
from x in list where x % 2 == 0 orderby x select x;
或
list .where(x => x % 2 == 0) .OrderBy(x => x)
可見,在LINQ中,一個表達式(函數)的返回結果作為令一個表達式(函數)的源,還可以進行多個鏈式。
比如讀取遠程數據。
void Main() { XDocument timeDoc; using(var client = new System.Net.WebClient()) { timeDoc = XDocument.Parse(client.DonwloadString("")); } var ms = Convert.ToInt64(timeDoc.Root.Attribute("time").Value) / 1000; var currentTime = new DateTime(1977,1,1).AddMilliseconds(ms).ToLocalTime(); Console.WriteLine(currentTime); }
對於using部分我們可以提煉出一個方法。
private XDocument GetTime() { using(var client = new System.Net.WebClient()) { return XDocument.Parse(client.DonwloadString("")); } } void Main() { var timeDoc = GetTime(); var ms = Convert.ToInt64(timeDoc.Root.Attribute("time").Value) / 1000; var currentTime = new DateTime(1977,1,1).AddMilliseconds(ms).ToLocalTime(); Console.WriteLine(currentTime); }
但,還不夠。以上的GetTime方法只是對WebClient這個實現了IDisposable接口的using語句進行了封裝,可不可以對所有實現IDisposable接口的類型的using語句進行封裝呢?
public static class MyDisposable { public static TResult Using<TDisposable, TResult>( Func<TDisposable> factory, Func<TDisposable, TResult> map) where TDisposable : IDisposable { using(var disposable = factory()) { return map(disposable); } } } void Main() { var time = MyDisposable .Using( () => new System.Net.WebClient(), client => XDocument.Parse(client.DownloadString("")) ) .Root .Attribute("time") .Value; var ms = Convert.ToInt64(time) / 1000; var currentTime = new DateTime().AddMilliseconds(ms).ToLocalTime(); Console.WriteLine(currentTime); }
在函數式編程中,函數返回的類型基本上另外一個函數方法的源實例。