副作用的概念:一個帶有副作用的函數不僅只是簡單的返回一個值,還干了一些其他的事情,比如:
-
-
- 修改一個變量
- 直接修改數據結構
- 設置一個對象的成員
- 拋出一個異常或以一個錯誤終止
- 打印到終端或讀取用戶的輸入
- 讀取或寫入一個文件
- 在屏幕上繪畫
-
因此我們對於函數式程序的判定邊界就在於:函數的副作用。
於是——當函數沒有副作用,那么我們就說這個函數符合函數式編程(FP);再給出純函數這個概念用來定義一個函數沒有副作用,我們可以說純函數構成的程序風格就是函數式的!
buyCoffee的例子(p3):函數只不過是需要返回一杯咖啡,可是卻對費用進行了持久化操作(產生副作用),我們可以在buyCoffee方法返回咖啡時也把費用作為值一並返回,將費用這條記錄交給其他程序來做持久化,以此來去除副作用 ====》通過把這些副作用推到程序的外層,來轉換任何帶有副作用的函數(純的內核和一層很薄的外圍來處理副作用)
引用透明:對於程序p,如果它包含的表達式e滿足引用透明,所有e都可以替換為它的運算結果而不會改變程序p的含義(要求函數不論進行任何操作都可以用它的返回值來代替)。
引用透明與純函數的關聯:假如存在一個函數f,若表達式f(x)對所有引用透明的表達式x也是引用透明,那么這個f是一個純函數(也就是說,傳入引用透明的x表達式給f,函數f(x)的返回值可以代替這個函數在其他程序起的作用)
純函數的好處:純函數是模塊化的、可組合的,因為它從“對結果做什么(返回值)”和“如果獲取輸入(通過參數傳遞獲得輸入)”中分離了計算本身的邏輯,就像一個黑盒子。