函數式編程中的基本概念

函數簽名

假設有一個函數 f,輸入一個 int 值,返回一個 string 值,在 C# 中,該函數能夠表示爲:編程

Func<int, string>

咱們能夠使用箭頭(→)符號來表示:緩存

f : int → string

箭頭符號是函數式編程社區的標準函數符號,與語言無關。函數式編程

當沒有輸入或沒有輸出(void)時,用 () 表示。若是有多個輸入或輸出,則用元組表示。函數

例如:this

Func<string>
Func<int, int, int>

分別表示爲:code

() → string
(int, int) → int

對於高階函數,能夠嵌套表示。作用域

例如 IEnumerable.Where 的簽名:string

Func<IEnumerable<T>, Func<T, bool>, IEnumerable<T>>

// IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate);

能夠表示爲:io

(IEnumerable<T>, (T → bool)) → IEnumerable<T>

函數的純潔性

純函數 是指沒有任何反作用的函數,除了根據輸入值計算輸出值以外,什麼也不作。而不純函數則可能致使反作用。社區

反作用包括:

  • 使全局狀態改變:這裏的「全局」是指函數做用域以外。
  • 改變其輸入參數
  • 拋出異常
  • 執行任何 I/O 操做

純函數擁有許多的好處:

  • 並行化:因爲輸出值僅依賴於輸入值,因此能夠並行執行任務。
  • 惰性求值
  • 記憶化:緩存函數結果,以便只計算一次。

誠實的函數

誠實的函數始終履行本身的簽名。

例如以下函數,就是一個誠實的函數:

public int Square(int n) => n * n;

而以下函數則是不誠實的:

public int Square(int n)
{
    if (n < 0) throw new ArgumentException();

    return n * n;
}

由於它可能返回一個 int 值,還可能拋出異常。


參考:《C# 函數式編程》 Enrico Buonanno 著

相關文章
相關標籤/搜索