函數式編程(一)

什麼是函數式編程

函數式編程是一種編程範式,常見的編程範式有如下三種:html

  • 命令式編程
  • 聲明式編程
  • 函數式編程

函數式編程的本質是將計算描述爲一種表達式求值。在函數式編程中,函數做爲一等公民,能夠在任何地方定義(在函數內或函數外),能夠做爲函數的參數和返回值,能夠對函數進行組合。git

函數式編程的準則:不依賴於外部的數據,並且也不改變外部數據的值,而是返回一個新的值給你。看個簡單的例子:web

// 非函數式的例子
    let count = 0;
    function increment() {
        count++; // 依賴於函數外部的值,並改變了它的值
    }
    
    // 函數式的例子
    function increment(count) {
        return count++;
    }

爲何採用函數式編程

函數式編程不依賴外部的狀態也不修改外部的狀態,函數調用的結果不依賴調用的時間和位置,這些寫代碼容易進行推理,不易犯錯,並且單測和調試都更簡單。即函數編程採用純函數。shell

純函數是這樣一種函數,即相同的輸入,永遠會獲得相同的輸出,並且沒有任何可觀察的反作用。

反作用可能包含,但不限於:數據庫

  • 更改文件系統
  • 往數據庫插入記錄
  • 發送一個 http 請求
  • 可變數據
  • 打印/log
  • 獲取用戶輸入
  • DOM 查詢
  • 訪問系統狀態
反作用是在計算結果的過程當中,系統狀態的一種變化,或者與外部世界進行的可觀察的交互。

純函數的好處:編程

純函數能根據輸入來作緩存(memoize技術)設計模式

const memoize = function(f) {
        const cache = {};
        return function() {
            const argStr = JSON.stringify(arguments);
            
            if (!cache[argStr]) {
                cache[argStr] = f.apply(f, arguments);
            }
            
            return cache[argStr];
        }
    }

可移植性/自文檔化
純函數的輸出只依賴與它的輸入,依賴很明確,易於理解。因爲純函數不依賴它的上下文環境,所以咱們能夠輕易的把它移植到任何地方運行它。瀏覽器

可測試性
咱們沒必要在每次測試前都去配置和構造初始環境,只需簡單給函數一個輸入,而後斷言它的輸出就行了。緩存

合理性
因爲純函數老是可以根據相同的輸入返回相同的輸出,因此它們就可以保證老是返回同一個結果,這也就保證了引用透明性。併發

並行執行
咱們能夠並行運行任意純函數。由於純函數根本不須要訪問共享的內存,並且根據其定義,純函數也不會因反作用而進入競爭態。
並行代碼在服務端 js 環境以及使用了 web worker 的瀏覽器那裏是很是容易實現的,由於它們使用了線程(thread)。不過出於對非純函數複雜度的考慮,當前主流觀點仍是避免使用這種並行。

實現函數式編程的技術

這裏咱們先不展開這些技術的細節內容,本文咱們先側重於對函數式編程有一個總體上的認識,具體的技術細節咱們將在下一章展開。

  • curry(柯里化)
  • compose(代碼組合)
  • Monad(Monad就是一種設計模式,表示將一個運算過程,經過函數拆解成互相鏈接的多個步驟。你只要提供下一步運算所需的函數,整個運算就會自動進行下去。)

如何正確看待函數式編程

咱們先來看如下幾種觀點:

  • 你這段代碼用了 for 循環,這是過程式的。爲了優雅,你應該寫成函數式的。
  • 你這段代碼有反作用,這是骯髒的。爲了純淨性,你應該把 IO 包在 Monad 裏。
  • 你這段代碼用了 class,這是面向對象的。爲了無狀態,你應該寫成高階函數。

我想說的是這種偏激的觀點是不正確的,咱們不該該把函數式編程和命令式編程對立起來,咱們更多的時候須要考慮的是技術的適用場景。函數式編程寫起代碼來,有必定的難度,若是一個團隊的總體水平達不到,那麼寫代碼的質量和效率還不如採用命令式編程好。函數式編程利用純函數的無狀態性,它的好處很是多(結果可預期、利於測試、利於複用、利於併發),但一個系統工程的代碼,是不可能所有采用純函數來寫的。當咱們越貼近業務,咱們就離純函數與無狀態越遠。

函數式編程很是重要,學習它咱們能打開咱們的思惟方式,使用它也有不少好處,但它也有一些侷限,咱們應該客觀看待。保持開放的心態,根據實際場景選擇合適的技術,是一個工程師基本的素養。

參考資料

https://llh911001.gitbooks.io...
http://www.ruanyifeng.com/blo...
https://coolshell.cn/articles...
https://www.zhihu.com/questio...
https://zhuanlan.zhihu.com/p/...

相關文章
相關標籤/搜索