.NET併發程式設計-函數語言程式設計

那是山發表於2021-01-30

本系列學習在.NET中的併發並行程式設計模式,實戰技巧

函數語言程式設計

和麵向過程程式設計POP(procedure oriented Programming)物件導向程式設計OOP(object oriented programming)一樣也是一種程式設計思維。函數語言程式設計FP(functional programming)和麵向過程比較類似,但它更加抽象。

舉個例子
五子棋,用程式導向程式設計開發流程就是: ①開始遊戲->②黑子先走->③繪製局勢->④判斷輸贏->⑤輪到白子->⑥繪製局勢->⑦判斷輸贏->⑧返回步驟②->⑨輸出結果,每一步驟寫成單獨的函式就是程式導向的程式設計思維。優點邏輯很清晰,較少的抽象。

物件導向程式設計可以從另外一個角度來解決這個問題,本質就是按功能角色劃分,將不同的函式封裝到不同的物件中。黑白雙方一個物件,棋盤物件用於繪製棋盤局勢,規則物件用於判斷輸贏是否五子連心。各個物件之間互相通知,互相協調。優點維護修改方便,如果換成圍棋,直接修改規則物件判斷棋子是否還有“氣”,或者通過物件導向特性去擴充套件一個物件。理解起來可能比較困難,實際程式碼執行可能分散到太多分支上。

面向函式程式設計呢?函式也是一個獨立的存在,它可以像變數一樣在任何地方出現。因為在程式導向中,不需要將函式做當方法來呼叫,直接在過程中呼叫,像Lambda表示式,對一個集合進行快速處理,不需要額外增加方法,呼叫出編寫一個臨時函式即可。

函式

先思考一個問題,函式一定要當做方法放在一個物件中嗎?答案是否定的,函式並不屬於物件,它是獨立的。在函數語言程式設計思維裡,函式可以通過變數,引數等方式傳遞到任何地方,可以在任何地方被呼叫,它和基本資料型別的待遇一樣。函式式語言一直以來都比較低調,直到併發計算程式設計瓶頸的出現。

實現併發

併發容易造成什麼問題?從單執行緒到多執行緒中,共享狀態的變化容易不受控制。傳統的解決方案就是同步對資源的訪問,避免執行緒之間的爭用。這樣也不是萬全之策,同步訪問互斥鎖容易出現競態和死鎖。根本的解決方案應該是不依賴於這些變數,既然是變數,就不能依賴於它的狀態。

FP在併發程式設計上的優勢

  • 不可變性。在FP中沒有變數賦值的概念。物件一旦確定值就不可更改,這線上程之間可以安全的傳輸。

  • 純函式。函式不會修改函式體之外的任何型別的輸入或資料,也就是純函式,沒有副作用(副作用就是相同的輸入可能產生不同的輸出)。輸出取決於輸出,相同的引數傳遞給純函式,輸出只會是相同的值,產生一致的預期行為。

  • 延遲計算。在FP中按需檢索函式的結果,或將大資料流的分析推遲到需要時。

  • 可組合性。組合函式建立更高階的抽象,有利用解決複雜問題。

NULL值的錯誤

高階語言一般都有NULL值型別。Tony Hoare在1965年設計ALGOL面嚮物件語言時引入了null引用。大約44年後,他為發明他道歉,稱它是10億美元的錯誤。

我無法抗拒引入null引用的誘惑,因為它非常容易實現。這導致了無數的錯誤、漏洞和系統崩潰。

 

 

F#是.NET語言的一部分,是一種函數語言程式設計語言。它就強烈反對null值,鼓勵使用不可變的資料結構,天生適用於併發。C#是在.NET3.5之後也引入函式式正規化,增加了諸如lambda表示式和LINQ之類的列表解析功能。因為都在.NET平臺上,F#和C#可以互操作,互相呼叫,有些複雜場景用F#可以用更簡易的方式實現。

to be contiued!
下集:併發函數語言程式設計技術

 

 

寫給普通:

人一旦得到一樣東西
就會忘記當初趴在櫥窗看它的感覺

相關文章