個人FP感悟

FP概要:

我主要總結了如下5點:

  1. 函數是一等公民: 函數的參數是函數,返回值是函數,類型仍是函數...
  2. 捨棄語句,擁抱表達式: 表達式就必定有返回值。
  3. 無反作用: 不修改外部系統的狀態。
  4. immutable: 沒有變量,一切不可變,循環用遞歸實現。
  5. 引用透明: 相同輸入產生相同輸出,須要的信息都經過參數傳遞,方便單元測試.

就以上幾點,我編了一首打油詩:java

函數編程很強大
一等公民都是它
外部變量不依賴
返回確保串行化

串行化什麼意思呢?
一樣計算(1+2)*3/4,java代碼以下:程序員

int a = 1 + 2
int b = a * 3
int c = b / 4

而Scala寫出來以下:編程

val r = subtract(multiply(add(1, 2), 3), 4)

如此,就能夠很簡單的改寫爲:設計模式

val r = add(1, 2).multiply(3).subtract(4)

其中的美妙本身體會吧~~~安全

那麼這麼作的意義呢?

  1. 代碼簡潔
  2. 接近天然語言
  3. 函數單純,易於測試
  4. immutable,併發簡單可控
  5. 熱升級
  • 若是代碼包含了任何的var,則是指令式風格,若是全是val則多是函數式風格。
  • 函數的結果類型是Unit的是有反作用的,而結果類型有明確返回類型的則多是沒有反作用的。
  • 函數內部依賴外部數據而不是輸入參數(也就是閉包)的是有反作用的, 而不依賴外部數據的可能沒有反作用.

函數式編程的歷史

有機會看到這篇文章的讀者,大概都會知道阿蘭·圖靈(Alan Turing)和約翰·馮·諾伊曼(John von Neumann)。阿蘭·圖靈提出了圖靈機的概念,約翰·馮·諾伊曼基於這一理論,設計出了第一臺現代計算機。多線程

因爲圖靈以及馮·諾伊曼式計算機的大獲成功,歷史差點淹沒了另一位一樣傑出的科學家和他的理論,那就是阿隆佐·邱奇(Alonzo Church)和他的λ演算。閉包

阿隆佐·邱奇是阿蘭·圖靈的老師,上世紀三十年代,他們一塊兒在普林斯頓研究可計算性問題,爲了回答這一問題,阿隆佐·邱奇提出了λ演算,其後不久,阿蘭·圖靈提出了圖靈機的概念,儘管形式不一樣,但後來證實,兩個理論在功能上是等價的,條條大路通羅馬。併發

若是不是約翰·麥卡錫(John McCarthy),阿隆佐·邱奇的λ演算恐怕還要在歷史的故紙堆中再多躺幾十年,約翰·麥卡錫是人工智能科學的奠定人之一,他發現了λ演算的珍貴价值,發明了基於λ演算的函數式編程語言:Lisp,因爲其強大的表達能力,一推出就受到學術界的熱烈歡迎,以致於一段時間內,Lisp 成了人工智能領域的標準編程語言。編程語言

很快,λ演算在學術界流行開來,出現了不少函數式編程語言:Scheme 、SML、Ocaml 等,可是在工業界,仍是命令式編程語言的天下,Fortran、C、C++、Java 等。函數式編程

隨着時間的流逝,愈來愈多的計算機從業人員認識到函數式編程的意義,愛立信公司於上世紀八十年代開發出了 Erlang 語言來解決併發編程的問題;
在互聯網的發展浪潮中,愈來愈多的語言也開始支持函數式編程:JavaScript、Python、Ruby、Haskell、Scala 等。

能夠預見,若是過去找一個懂什麼是函數式編程的程序員很困難,那麼在不久的未來,找一個一點也沒聽過函數式編程的程序員將更加困難。

面向對象編程

對於面向對象,咱們已經再熟悉不過了,因此這裏不作過多介紹,直接分析它的優缺點.

面向對象編程的優勢

面向對象程序設計能夠看做一種在程序中包含各類獨立而又互相調用的對象的思想(抽象現實世界),這與傳統的思想恰好相反。

傳統的程序設計主張將程序看做一系列函數的集合,或者直接就是一系列對電腦下達的指令。

面向對象程序設計中的每個對象都應該可以接受數據、處理數據並將數據傳達給其它對象,所以它們均可以被看做一個小型的「機器」,即對象。

目前已經被證明的是,面向對象程序設計推廣了程序的靈活性和可維護性,而且在大型項目設計中廣爲應用。

此外,支持者聲稱面向對象程序設計要比以往的作法更加==便於學習==(因此易於推廣),由於它可以讓人們更簡單地設計並維護程序,使得程序更加便於分析、設計、理解。

同時它也是易拓展的,因爲繼承、封裝、多態的特性,天然設計出高內聚、低耦合的系統結構,使得系統更靈活、更容易擴展,並且成本較低。

在面向對象編程的基礎上發展出來的23種設計模式普遍應用於現今的軟件工程中,極大方便了代碼的書寫與維護。

  • 建立型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
  • 結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
  • 行爲型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。

面向對象編程的缺點

  • (多併發問題)面向對象編程以數據爲核心,因此在多線程併發編程中,多個線程同時操做數據的時候可能會致使數據修改的不肯定性。
  • 在如今的軟件工程中,因爲面向對象編程的濫用,致使了不少問題。
    • (冗餘度大)首先就是爲了寫可重用的代碼而產生了不少無用的代碼,致使代碼膨脹.
    • (難理解,難維護)同時不少人並無徹底理解面向對象思想,爲了面向對象而面向對象,使得最終的代碼晦澀難懂,給後期的維護帶來了很大的問題。
    • (大型系統不適應)因此對於大項目的開發,使用面向對象會出現一些不適應的狀況。
  • (低效率)面向對象雖然開發效率高可是代碼的運行效率比起面向過程要低不少,這也限制了面向對象的使用場景不能包括那些對性能要求很苛刻的地方。

下面咱們在看看函數式編程(FP)

什麼是函數式編程(FP)

狹義地說,函數式編程沒有可變的變量、循環等這些命令式編程方式中的元素,像數學裏的函數同樣,對於給定的輸入,無論你調用該函數多少次,永遠返回一樣的結果。而在咱們經常使用的命令式編程方式中,變量用來描述事物的狀態,整個程序,不過是根據不斷變化的條件來維護這些變量。

廣義地說,函數式編程重點在函數,函數是這個世界裏的==一等公民==,函數和其餘值同樣,能夠處處被定義,能夠做爲參數傳入另外一個函數,也能夠做爲函數的返回值,返回給調用者。利用這些特性,能夠靈活組合已有函數造成新的函數,能夠在更高層次上對問題進行抽象。本文的重點將放在這一部分。

函數式編程的優勢

  • (不可變,易併發)在函數式編程中,因爲數據所有都是不可變的,因此沒有併發編程的問題,是多線程安全的。
  • (數據一致,結果穩定)能夠有效下降程序運行中所產生的反作用,對於快速迭代的項目來講,函數式編程能夠實現函數與函數之間的熱切換而不用擔憂數據的問題,由於它是以函數做爲最小單位的,只要函數與函數之間的關係正確便可保證結果的正確性。
  • (可讀性強)函數式編程的表達方式更加符合人類平常生活中的語法,代碼可讀性更強。
    實現一樣的功能函數式編程所須要的代碼比面向對象編程要少不少,代碼更加簡潔明晰。
  • 函數式編程普遍運用於科學研究中,由於在科研中對於代碼的工程化要求比較低,寫起來更加簡單,因此使用函數式編程開發的速度比用面向對象要高不少,若是是對開發速度要求較高可是對運行資源要求較低同時對速度要求較低的場景下使用函數式會更加高效。

函數式編程的缺點

  • (變量消耗內存)因爲全部的數據都是不可變的,因此全部的變量在程序運行期間都是一直存在的,很是佔用運行資源。
  • (運行速度慢)同時因爲函數式的先天性設計致使性能一直不夠。雖然現代的函數式編程語言使用了不少技巧好比惰性計算等來優化運行速度,可是始終沒法與面向對象的程序相比,固然面向對象程序的速度也不夠快。
  • (不普及)函數式編程雖然已經誕生了不少年,可是至今爲止在工程上想要大規模使用函數式編程仍然有不少待解決的問題,尤爲是對於規模比較大的工程而言。若是對函數式編程的理解不夠深入就會致使跟面相對象同樣晦澀難懂的局面。

總結

函數式編程和麪向對象編程各有利弊,一個語法更加自由(FP),一個健壯性更好(OOP)。做爲程序員應該對兩種編程方式都有所瞭解,無論是哪一種方式,只要可以很好的解決當前的問題就是正確的方式,畢竟對於軟件工程來講解決問題是最主要的,用的工具反而沒有那麼重要,就像對程序員來講語言不重要,重要的是解決問題的思想。

如今這二者的發展趨勢是相互借鑑的,許多以面向對象做爲基礎的語言例如Java等都在新的版本中添加了對函數式編程的支持,而函數式編程則借鑑了一些在面嚮對象語言裏用的一些編譯技巧使得程序運行更快。

細說FP的優勢

約翰·巴克斯(John Backus)爲人熟知的兩項成就是 FORTRAN 語言和用於描述形式系統的巴克斯範式,由於這兩項成就,他得到了 1977 年的圖靈獎。

有趣的是他在獲獎後,作了一個關於函數式編程的講演:Can Programming Be Liberated From the von Neumann Style? 1977 Turing Award Lecture。他認爲像 FORTRAN 這樣的命令式語言不夠高級,應該有新的,更高級的語言能夠擺脫馮諾依曼模型的限制,因而他又發明了 FP 語言,雖然這個語言未獲成功,可是約翰·巴克斯關於函數式編程的論述卻獲得了愈來愈多的承認。下面,咱們就羅列一些函數式編程的優勢。

首先,函數式編程自然有併發的優點。因爲工藝限制,摩爾定律已經失效,芯片廠商只能採起多核策略。程序要利用多核運算,必須採起併發,而併發最頭疼的問題就是共享數據,狹義的函數式編程沒有可變的變量,數據只讀不寫,併發的問題迎刃而解。這也是前面兩篇文章中,一直建議你們在定義變量時,使用 val 而不是 var 的緣由。愛立信公司發明的 Erlang 語言就是爲解決併發的問題而生,在電信行業取得了不俗的成績。

其次,函數式編程有跡可尋。因爲不依賴外部變量,給定輸入函數的返回結果永遠不變,對於複雜的程序,咱們能夠用值替換的方式(substitution model)化繁爲簡,輕鬆得出一段程序的計算結果。爲這樣的程序寫單元測試也很方便,由於不用擔憂環境的影響。

最後,函數式編程高屋建瓴。寫程序最重要的就是抽象,不一樣風格的編程語言爲咱們提供了不一樣的抽象層次,抽象層次越高,表達問題越簡潔,越優雅。讀者從下面的例子中能夠看到,使用函數式編程,有一種高屋建瓴的感受。

相關文章
相關標籤/搜索