<optgroup id="2ys2g"><button id="2ys2g"></button></optgroup>
  • <small id="2ys2g"><tr id="2ys2g"></tr></small>

    面向函數范式編程(Functional programming)

      函數編程(簡稱FP)不只代指Haskell Scala等之類的語言,還表示一種編程思維,軟件思考方式,也稱面向函數編程。 編程的本質是組合,組合的本質是范疇Category,而范疇是函數的組合。

      首先,什么是函數式編程,這并沒有唯一定義,它只是廣泛聚合了一些編程風格的特性,我們可以將它與面向對象編程OOP進行對比, 兩者區別是,OOP主要聚焦于數據的區別,而FP則注重數據結構的一致性。OOP最大優點是多態性和封裝;而FP優勢是不變性及其聲明性風格,兩者其實是正交,可互補的,可在同一程序中共存。

    面向對象:

    1. 數據和對數據的操作緊緊耦合
    2. .對象隱藏它們操作的實現細節,其他對象調用這些操作只需要通過接口。
    3. .核心抽象模型是數據自己
    4. 核心活動是組合新對象和拓展已經存在的對象,這是通過加入新的方法實現的。

    函數編程:

    1. 數據與函數是松耦合的
    2. 函數隱藏了它們的實現,語言的抽象是函數,以及將函數組合起來表達。
    3. 核心抽象模型是函數,不是數據結構
    4. 核心活動是編寫新的函數。
    5. 變量缺省是不變的,減少可變性變量的使用,并發性好

      那么OOP和FP在業務領域是否有勝者呢? 我們大部分業務邏輯是這樣寫:


    SELECT orders.order_id, orders.order_date, suppliers.supplier_name
      FROM suppliers
      RIGHT OUTER JOIN orders
      ON suppliers.supplier_id = orders.supplier_id
      WHERE orders.order_status = 'INCOMPLETE'
      ORDER BY orders.order_date DESC;

      SQL是非常類似FP,它能滲透到業務中,它使用一致的數據結構(數據表結構Schema),一些基本函數能組合成很多查詢語句,它是declarative聲明式的, 也就是說,寫出的SQL是告訴數據庫我需要什么,數據庫就為你返回,而不必指定數據庫如何具體去查詢。

      聲明式編程和命令式編程區別? FP的主要特點是它們描述它們要"什么",而不是如何實現。而OO在其方法中,還是使用大部分命令式技術。 下面是命令式技術代碼:

    var sumOfSquares = function(list) {
      var result = 0;
      for (var i = 0; i < list.length; i++) {
        result += square(list[i]);
      }
      return result;
    };

    console.log(sumOfSquares([2, 3, 5]));

    函數編程代碼如下:
    var sumOfSquares = pipe(map(square), reduce(add, 0));
    console.log(sumOfSquares([2, 3, 5]));

      函數風格的編程特點:

    1. 第一等公民是函數
    2. 帶有閉包的Lambdas/Anonymous函數
    3. 不變性,大部分無態處理,沒有狀態和變量
    4. 高并發
    5. 無副作用的調用
    6. 通過tail call實現遞歸的性能優化。
    7. 模式匹配(Haskell, Erlang)
    8. 懶賦值(Miranda, Haskell)
    9. Homoiconicity(類似LISP)

      如果說OOP還有很多人可能受靜態數據思路影響,那么FP 帶來完全是動態事件,FP讓我們直接用動詞思考,用方法函數解決問題,比如兩個帳號之間的轉帳,按照DDD等靜態領域建模思維,轉帳這個功能是放在帳號這個實體類中,還是做一個服務呢?在OOP語言中,我們實現功能總是使用服務Service這樣一個概念替代,而且強調無態服務,無態服務實際就是一個只有方法函數沒有屬性的空架子“類”而已。 2007年的Adam Heroku一篇博文中寫道:銀行賬戶之間轉帳的老式做法是使用數據庫事務,這種做法比較剛性,正確做法是將轉帳事件存儲起來,如果你是一個面向函數范式的思維者覺得這樣做就很正常。---來自" NOSQL存儲的基于事件的事務實現 " 。

      有很多人將FP歸結于數學思維,實際上這只看到其表面,沒有看到數學語言這個背后的形式邏輯,編程語言作為和數學同等形式語言,他們的核心基礎都是分析哲學的形式邏輯,過去的面向對象很多設計原則也來源于形式邏輯,見:蒯因與引用透明 。  

      面向對象和面向函數一直在爭論,實際上純粹的OOP和純粹的FP都是極端的,對于OOP來講:存在的并一定都是對象,函數就不是對象;對于FP來說:存在的并不總是純粹的,副作用總是真實存在。總之,面向對象側重于分解,函數編程側重于組合。

     

    文章

    類型系統和邏輯

    函數式編程模式:單位元(幺元)

    函數式編程模式:半群

    范疇category:組合的本質

    什么是Monoid ?

    什么是Monad?

    為什么需要Monad??

    面向對象與函數編程的比較

    OOP和FP錯在哪里?

    為什么組合好于繼承??

    什么是流式思維?

    Reactive設計語言與范式

    蒯因與引用透明

    為什么我再也不使用MVC框架了?

    微服務的最終一致性與事件流

    一張圖解說Map/filter/reduce

    從CRUD編程切換到事件溯源和區塊鏈編程

    一篇有關函數式編程的形象生動教程

    Java8

    Closure Lambda和Monad

    分分鐘學會Java8的Lambda

    Java 8十個lambda表達式案例

    Java8教程

    使用Java8的Lambda實現的一個簡單案例

    使用Java8的Lambda實現Monda

    使用Java8的Lambda實現模板模式

    使用Java8的Lambda實現策略模式

    Java8的Lambda和排序

    用Java 8 lambda優化JDBC

    使用Java8的Lambda簡化ReadWriteLock

    Java 8的Lambda表達式的陰暗面

    用monad替代嵌套回調

    更多Java8專題

     

    其他語言

    HASKELL入門起步

    Scala入門之函數編程

    Scala入門之基本概念

    更多Scala專題

    Javascript閉包是什么?

    Scala中文教程和手冊

    蘋果Swift語言中文簡明教程

    Javascript的函數式編程術語解釋

     

    參考

    Python語言教程手冊

    Reactive專題

    面向函數編程系列專題

    EventSourcing  

    形式邏輯專題

    Node.js專題

     

    美女漫画大全