若想實現一個將多位數組的數值累加的總和的需求:
方式一:
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)
優點:
- 編寫的函數高內聚,低耦合
- 提高了可復用性
- 無臨時變量過多或堆棧過多導致的副作用。
無副作用(side-effect free) 和 不包含賦值語句 (contain no assignment statements)。因此,表達式可以在任何時候計算並替換為其值, 這樣程序就是引用透明的(referentially transparent)。即使到了今天也經常討論計算時值不可變(value of immutability)和無副作用(side-effect free) - 只是計算過程,內部無狀態,從而可以在並發的情況保證狀態一致。
函數式編程的三大特性:
- 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 高階函數:
所謂高階函數就是函數當參數,把傳入的函數做一個封裝,然后返回這個封裝函數。現象上就是函數傳進傳出,就像面向對象對象滿天飛一樣。
