在數學的定義裡,一對一或多對一的對應就是所謂的函數(function),而pure function則是使用了這個數學定義,只要輸入值是固定的東西,每次輸出的結果也會是相同的。
以array method來看,slice()與splice()一個是純的另一個不是,兩者分別經過三次呼叫的結果完全不同。把arr陣列視為input,回傳的結果則為output,能發現丟arr進slice(),無論幾次的輸出的都是[1,2],這是pure function的特性;而丟splice()卻每次得到不同結果,這不是pure function。
實際上因為把arr丟進slice,因為會回傳一個新的矩陣,原本的arr陣列沒有被改變,所以三次呼叫的結果都相同;而splice則是因為會真的從原本的arr矩陣移除東西,所以每次回傳的結果因而不同。
const arr = [1, 2, 3, 4, 5];
console.log(arr.slice(0, 2)); //[1,2]
console.log(arr.slice(0, 2)); //[1,2]
console.log(arr.slice(0, 2)); //[1,2]
console.log(arr.splice(0, 2)); //[1,2]
console.log(arr.splice(0, 2)); //[3,4]
console.log(arr.splice(0, 2)); //[5]
另一個例子是,當函式所依賴的變數是在全域宣告的,這代表這個函式的輸出結果,其實很大程度是與環境的狀態綁在一起,所以無法確保輸入相同的東西,每次都會回傳一樣的結果,於是也看成impure。
function pure(input) {
let localVar = 10;
return input + localVar;
}
console.log(pure(5)); //15
console.log(pure(5)); //15
console.log(pure(5)); //15
let globalVar = 10;
function impure(input) {
return (globalVar += input);
}
console.log(impure(5)); //15
console.log(impure(5)); //20
console.log(impure(5)); //25
常聽說在開發過程中,需要變更時會發生的慘劇是改了這個,那個就壞了,當函式的執行會有無法掌握的副作用
,這個結局好像是無可避免的。如果使用的是pure function就可以更單純地思考問題本質,而不會牽一髮而動全身。
當函式的執行可以不影響其他程式時,就可以像組裝積木般輕鬆組合在一起,形成更大的功能塊,而不會引入意外的行為或副作用。這使得程式碼更加模組化和易於理解。
一個函數是純函數(Pure Function)時,它的輸出只依賴於輸入,並且不會改變外部的狀態。這樣的函數具有高可預測性,使得測試變得非常容易和可靠。
當執行非同步程序時,因為無法確定哪個會先做完,如果此時又依賴相同的變數或記憶體位置,很容易因為這個不確定性而產生意外的錯誤,但若使用pure function,因為函式執行時不依賴外部狀態,則可避免這樣的狀況。
pure function是functional programming的核心概念,藉此可以實現用數學來看程式,但到處都要寫pure function其實不是一件簡單的事,可能需要更多工具來讓一切更容易點,像是以柯里化來處理多個引數傳遞的狀況,我感覺這一切才剛開始...
Proessor Frisby's Mostly Adequate Guide to Functional Programming 中譯
純粹的好,Pure Function 知道
嵌射、蓋射與對射