Function Programming - 純函數(Pure Function)
純函數的定義,非常重要!!
Pure function 意指相同的輸入,永遠會得到相同的輸出,而且沒有任何顯著的副作用。
老樣子,我們還是從最簡單的栗子開始:
var minimum = 21; var OutercompareNumber = function(number) { return number > minimum; } 以及 var InnercompareNumber = function(number) { var minimum = 21; return number > minimum; }
以上兩個函數的區別大家都看到了,一個minimum定義在函數外面,一個在函數裏面;那麽我們調用這兩個函數的結果就很有可能是不一樣的;比如,我們在調用OutercompareNumber的時候,假設number這個參數我們始終傳20,minimum不改變的情況下,結果為false;但一旦minimum改變成19,結果就為true,OutercompareNumber就不是pure的函數;而InnercompareNumber這個函數,如果始終傳20,結果始終為false,那麽我們就說InnercompareNumber為純函數(pure function)。
總結來說,就是傳的參數相同的情況下,永遠會得到相同的輸出。
那麽我們說的顯著的副作用又是什麽呢?我們來看下定義:副作用是在計算結果的過程中,系統狀態的一種改變,或是外部世界可觀察的交互作用。
比如,更改檔案系統,發送http請求等,只要與function外部環境發生交互作用的都是副作用。
那麽,如何避免這些副作用呢,繼續來看栗子:
var callRequest = function(url, params) { return $.getJSON(url, params); } 與 var delayCallRequest = function(url, params) { return function() { return $.getJSON(url, params); } }
callRequest直接返回了一個http請求,那麽這個是與外界交互,返回的結果有太大的不確定性,所以是impure的函數;而delayCallRequest采用了延遲執行的方式,返回了一個函數,只有調用這個函數的時候才會發送請求:delayCallRequest(url, params)(),但就delayCallRequest而言,傳相同的參數,得到的結果是一樣的,是相同參數的函數,所以這個是一個pure的函數。
再看一個栗子,我們深入理解一下:
//impure var signUp = function(attrs) { var user = saveUser(attrs); welcomeUser(user); }; var saveUser = function(attrs) { var user = Db.save(attrs); ... }; var welcomeUser = function(user) { Email(user, ...); ... }; //pure var signUp = function(Db, Email, attrs) { return function() { var user = saveUser(Db, attrs); welcomeUser(Email, user); }; }; var saveUser = function(Db, attrs) { ... }; var welcomeUser = function(Email, user) { ... };
pure函數會自給自足,函數的依賴會特別明確,像impure的函數,Email做了什麽我們並不知道,Db在背後做了什麽,我們也無所得知,所以他們以參數的形式,保證輸入相同的情況下,得到的結果一定是相同的,註意,這裏也用了延遲執行的方式。
好啦,今天的純函數就介紹到這裏,我們下回再見~~早安!
Function Programming - 純函數(Pure Function)