---
# System prepended metadata

title: 數學是有用的 - Functional Programming
tags: [Functional Programming]

---

---
tags: Functional Programming
---

# 數學是有用的 - Functional Programming

Functional Programming (以下簡稱 **FP** )是一種編程範式，FP 的核心思想就是透過 **function** 來解決各種問題，並且所有的 **function** 都是以「**數學函數**」為模型。

在 FP 裡 function 是有更明確的定義：

> 「functions 是一種表達式，可以輸入參數，一但輸入參數後就可以**被簡化(reduced)** 或是說 **被運算(evaluated)**」


### 更明確的來說

在 FP 裡，function 就像是**數學函式**一樣：

![FP-pic](https://i.imgur.com/90aGb8e.png)


在這個情況下來看，f 就非常符合 FP 對於 function 的規範，給定參數，不管試驗幾次都**只會出現同一個結果**：

$f(1) = A$

$f(2) = B$

$f(3) = C$

那如果是以下這種情況呢：

![FP-pic](https://i.imgur.com/6bjqePS.png)


這裡 f 不管是傳入 1、2 還是 3 都會回傳 A，這也是可以的，我們**只要確保如果傳入相同的參數**，永遠會回傳相同的值。

而我覺得 FP 最精華的概念就是這一句話，來自這個[影片](https://www.youtube.com/watch?v=e-5obm1G_FY&t=305s)。

> How we can express everything in terms of function 。

總的來說 FP 是：

- Style / Pattern 一種撰寫風格
- Paradigm 一種規範
- Mindset 抽象式思維

有別於老大哥 OOP(或其他 OO 系列)，FP則是近年來較為熱門的編程範式。像是 React 這套 JavaScript 框架就是使用FP來開發程式。

## FP 的核心觀念
在 FP 中，既然要把 function 當作最核心的元件，不斷地以 function 為單位解決問替，就需要對 function 有些特別的定義，例如：

### 一等公民 (First-Class)

所謂的一等公民指的是 function 跟其他資料型別是**具有相同的地位**

也就是說 function 要可以被當成參數、回傳值，也可以賦值給變數或是存在資料結構中：

```jsx
function request(onSuccess) { // onSuccess 是一個 function 被當作參數傳給 request
  // ...
  // onSuccess(data) 
}

function add (x) {
  return function (y) { // function 被當作 add 的回傳值
    return x + y;
  }
}

const hello = () => 'hello world!'; // function 當作 value 賦值給 hello 變數
```

任何一個想要實作 FP 的語言，都至少要能夠符合一等公民這個條件。

### [Side Effect 和 Pure Function](https://hackmd.io/@ChrisW/rJT588049)

如果我們想要完全符合數學函數的型態 ---- 也就是「same input same out put」。

就必須保證 function 不會產生任何我們**預期外的不可控因素**，而這個也可以稱之為 **Side Effect**。

side effect 可以理解成「在運算的過程中，改變了系統狀態或是對外部世界進行交互」。

總歸一句話來講，跟 **output 沒關係的動作**都會被視為 Side Effect。

就例如下面的這個例子：

```javascript=
let numArr = [5,3,17,2,7]

function sortByDesc(arr){
    return arr.sort((a,b)=>b-a)
}

sortByDesc(numArr) // 17 7 5 3 2
```

乍看之下可能是個很正常的 function，same input same output 的準則也沒錯，但因為他**改變到了外部狀態**`numArr`，所以這個 function 就擁有 Side Effect。
```javascript=
console.log(numArr) // 17 7 5 3 2
```

可以把它解構，讓程式不認為他們是同一個，就可以不去影響到外部物件，就不再被視為 Side Effect:
```javascript=
let numArr = [5,3,17,2,7]

function sortByDec(arr){
    return [...arr].sort((a,b)=>b-a)
}

console.log(sortByDec(numArr)) // 17 7 5 3 2
console.log(numArr) // 5 3 17 2 7
```
相同的例子還有很多，例如使用 `A.push(B)` 不如 `[...A,...B]`、使用 `splice()` 不如 `slice()`等等很多例子，更詳細的可以去看看 [這篇](https://hackmd.io/@ChrisW/rJT588049) ，這邊只是稍微有個認知就好。

說到這邊，如果你對 side Effcet 有一些基礎認知的話，那你也知道 Pure Function 是什麼了，因為 Pure Function **就是沒有 Side Effect 的 function**。

## why Pure
除了為了符合 FP 的定義以外，遵守這些準則有什麼好處呢，我們可以將其大概的列出來：

### 可預期
same input same output

### 容易理解
程式碼乾淨，且不用擔心會影響到外部因素，看一次就懂

### 可組合，可分割，可重用
藉由以上兩點，就可以不斷的使用定義好的程式碼，除了符合 DRY(Dont repeat your code) 以外，還能使用 [compose & pipe](https://hackmd.io/p0NIKWclR_qOfPibQC_q9w) 打造快速開發的且愉快得 DX 體驗。

### 可快取 (Cache)
因為 Same inpur Same output，所以我們再做類似動態規劃的運算時，就可以大大的省略重複計算的空間和效能浪費。

### 可延遲運算 (Lazy Evaluation)
因為不會有額外side effect，因此可以使用 [Curry - 不是吃的也不會射三分](/T2ODjTcrTJW9Z2xExurFsg) 的方式放心的將程式碼包裝，組合成更強大的功能，或是把side effect排除，如下：
``` javascript=
const pureHttpCall = memoize(function(url, params) {
  return function() {
    return $.getJSON(url, params);
  };
});
```
> 因為我們並沒有真的發送 request，而是把 request 包裝起來，並記住這次傳入的變數，留待下次再使用，因此不算產生 side effect

### 可並行運算
我們可以並行的執行任何 function，因為 Pure Function 不會依賴外部狀態，也就是不需要共享記憶體，同時也不會有其他任何side effect，也因此不會有競爭危害 (race condition)的問題

## FP 延伸概念

- [高階函數 HOC / HOF](https://www.notion.so/HOC-HOF-550abf8c80444711a8d1637f0e6e0e53)
- [IIFE](https://www.notion.so/IIFE-01d571b82c264f4ab4c43004b9db3380)
- [Closure](https://www.notion.so/Closure-b8e0ab2ca48844649bc8115ff772818e)
- [Function Declarations vs. Expressions](https://www.notion.so/Function-Declarations-vs-Expressions-8f79e2300bc64f6f89634814da06ab94)


> 其他大神寫好的概述可以看[這裡](https://codewords.recurse.com/issues/one/an-introduction-to-functional-programming)

# 參考連結

[https://jigsawye.gitbooks.io/mostly-adequate-guide/content/ch4.html](https://jigsawye.gitbooks.io/mostly-adequate-guide/content/ch4.html)

[https://totoroliu.medium.com/javascript-functional-programming-函式編程概念-e8f4e778fc08](https://totoroliu.medium.com/javascript-functional-programming-%E5%87%BD%E5%BC%8F%E7%B7%A8%E7%A8%8B%E6%A6%82%E5%BF%B5-e8f4e778fc08)

[https://ithelp.ithome.com.tw/articles/10233399](https://ithelp.ithome.com.tw/articles/10233399)

[https://developer.mozilla.org/zh-TW/docs/Glossary/First-class_Function](https://developer.mozilla.org/zh-TW/docs/Glossary/First-class_Function)

[https://medium.com/一個小小工程師的隨手筆記/javascript-functional-programming-一文到底全紀錄-95ff19d9892](https://medium.com/%E4%B8%80%E5%80%8B%E5%B0%8F%E5%B0%8F%E5%B7%A5%E7%A8%8B%E5%B8%AB%E7%9A%84%E9%9A%A8%E6%89%8B%E7%AD%86%E8%A8%98/javascript-functional-programming-%E4%B8%80%E6%96%87%E5%88%B0%E5%BA%95%E5%85%A8%E7%B4%80%E9%8C%84-95ff19d9892)

[https://jigsawye.gitbooks.io/mostly-adequate-guide/content/ch2.html](https://jigsawye.gitbooks.io/mostly-adequate-guide/content/ch2.html)