一個小例子說明函數式編程


若想實現一個將多位數組的數值累加的總和的需求:

方式一:

let arr = [1, [2, 2], [3, 3]];
let arr1 = arr.flat(Infinity).reduce((total, value, index, arr) => {
  return total + value;
}, 0);
console.log('arr1:', arr1);

通過函數式編程方式

方式二:

//es5

function add(x) {
  return function addFun(y) {
    if (y) {
      return add(x + y);  //可以遞歸多次調用,但需要之后一次調用()執行
    } else {
      return x;
    }
  }
}

let result = add(1)(2)(3)();
console.log('add(1)(2)(3)():', result);

let arr2 = arr.flat(Infinity).reduce((totalFun, value) => { return totalFun(value); }, add);
console.log('arr2:', arr2());

方式三:

//es6方式

let sum = (x) => (y => {
  if (y) {
    return sum(x + y);
  }
  return x;
});
let sum1 = sum(1);
let sum2 = sum1(2);
console.log(`sum2:${sum2},\r\n result:${sum2()}`);

道破:

一下內容來源:(謝各位大神的指導)
內容若有問題,各位客官可留言,我會及時修復di~。
[1] (https://blog.csdn.net/archimelan/article/details/81940858)
[2] (https://www.cnblogs.com/xingxueliao/p/11649873.html)
[3] (https://blog.csdn.net/weixin_43430036/article/details/93721442#_140)
[4] (https://www.liaoxuefeng.com/wiki/897692888725344/923030136026784)

優點:

  1. 編寫的函數高內聚,低耦合
  2. 提高了可復用性
  3. 無臨時變量過多或堆棧過多導致的副作用。
    無副作用(side-effect free) 和 不包含賦值語句 (contain no assignment statements)。因此,表達式可以在任何時候計算並替換為其值, 這樣程序就是引用透明的(referentially transparent)。即使到了今天也經常討論計算時值不可變(value of immutability)和無副作用(side-effect free)
  4. 只是計算過程,內部無狀態,從而可以在並發的情況保證狀態一致。

函數式編程的三大特性:

  • immutable data 不可變數據:
      像Clojure一樣,默認上變量是不可變的,如果你要改變變量,你需要把變量copy出去修改。這樣一來,可以讓你的程序少很多Bug。因為,程序中的狀態不好維護,在並發的時候更不好維護。(你可以試想一下如果你的程序有個復雜的狀態,當以后別人改你代碼的時候,是很容易出bug的,在並行中這樣的問題就更多了)
  • first class functions:
      這個技術可以讓你的函數就像變量一樣來使用。也就是說,你的函數可以像變量一樣被創建,修改,並當成變量一樣傳遞,返回或是在函數中嵌套函數。這個有點像Javascript的Prototype(參看Javascript的面向對象編程)
  • 尾遞歸優化:
      我們知道遞歸的害處,那就是如果遞歸很深的話,stack受不了,並會導致性能大幅度下降。所以,我們使用尾遞歸優化技術——每次遞歸時都會重用stack,這樣一來能夠提升性能,當然,這需要語言或編譯器的支持。Python就不支持。

函數式編程的幾個技術

  • map & reduce :
      這個技術不用多說了,函數式編程最常見的技術就是對一個集合做Map和Reduce操作。這比起過程式的語言來說,在代碼上要更容易閱讀。(傳統過程式的語言需要使用for/while循環,然后在各種變量中把數據倒過來倒過去的)這個很像C++中的STL中的foreach,find_if,count_if之流的函數的玩法。
  • pipeline:
      這個技術的意思是,把函數實例成一個一個的action,然后,把一組action放到一個數組或是列表中,然后把數據傳給這個action list,數據就像一個pipeline一樣順序地被各個函數所操作,最終得到我們想要的結果。
  • recursing 遞歸 :
      遞歸最大的好處就簡化代碼,他可以把一個復雜的問題用很簡單的代碼描述出來。注意:遞歸的精髓是描述問題,而這正是函數式編程的精髓。
  • currying:
      把一個函數的多個參數分解成多個函數, 然后把函數多層封裝起來,每層函數都返回一個函數去接收下一個參數這樣,可以簡化函數的多個參數。在C++中,這個很像STL中的bind_1st或是bind2nd。
  • higher order function 高階函數:
      所謂高階函數就是函數當參數,把傳入的函數做一個封裝,然后返回這個封裝函數。現象上就是函數傳進傳出,就像面向對象對象滿天飛一樣。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM