函數簽名 假設有一個函數 f,輸入一個 int 值,返回一個 string 值,在 C# 中,該函數可以表示為: Func<int, string> 我們可以使用箭頭(→)符號來表示: f : int → string 箭頭符號是函數式編程社區的標準函數符號,與語言無關。 當沒有輸入或沒有輸出(vo ...
函數簽名
假設有一個函數 f
,輸入一個 int
值,返回一個 string
值,在 C# 中,該函數可以表示為:
Func<int, string>
我們可以使用箭頭(→)符號來表示:
f : int → string
箭頭符號是函數式編程社區的標準函數符號,與語言無關。
當沒有輸入或沒有輸出(void)時,用 ()
表示。如果有多個輸入或輸出,則用元組表示。
例如:
Func<string>
Func<int, int, int>
分別表示為:
() → string
(int, int) → int
對於高階函數,可以嵌套表示。
例如 IEnumerable.Where
的簽名:
Func<IEnumerable<T>, Func<T, bool>, IEnumerable<T>>
// IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate);
可以表示為:
(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 著