# Currying
###### tags: `Javascript`
ref: https://javascript.info/currying-partials
什麼是 Curring ? 簡單來說就是:
f(a, b, c) 轉換成 f(a)(b)(c) 這種呼叫法也可以成功,這個轉換過程就是 Currying 。
```javascript=
function curry(f) { // curry(f) does the currying transform
return function(a) {
return function(b) {
return f(a, b);
};
};
}
// usage
function sum(a, b) {
return a + b;
}
let curriedSum = curry(sum);
alert( curriedSum(1)(2) ); // 3
```
常見用的用法是把要使用到的函式(sum)指派給一個變數(curriedSum),並且用那個變數來進行呼叫執行整個過程。
* 首先 curry(func) 是 function(a) 的包裹物。
* 接下來操作 curriedSum(1) ,這時參數 (1)會被存在 Lexical Environment 內,並且 return 一個新的 function(b) 包裹物。
* 最後這層 function(b) 包裹物使用參數 (2) ,並且傳入最原本的 sum()。
## 所以 Currying 的目的是什麼?
```javascript=
function log(date, importance, message) {
alert(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`);
}
```
為了理解 Currying 這邊使用了一個 log(date, importance, message),舉例說明:
第一步驟對其做 Currying ,使用 loadsh 函式庫來處理。
```javascript=
log = _.curry(log);
```
這個函式正常運作下長這樣:
```javascript=
log(new Date(), "DEBUG", "some debug"); // log(a, b, c)
```
然後因為剛剛操作上 Currying 所以我們也可以這樣去呼叫 log 函式
```javascript=
log(new Date())("DEBUG")("some debug"); // log(a)(b)(c)
```
重點來了:
我們可以藉由 Currying 來部分的操作函式的功能,以下方的 logNow 舉例,因為它直接操作了部分的 new Date() 功能先行寫入,所以接下來操作 LogNow 就不需要在帶入 new Date() 做為參數。
文章內的 “partially applied function” 就是這個意思
```javascript=
// logNow will be the partial of log with fixed first argument
let logNow = log(new Date());
// use it
logNow("INFO", "message"); // [HH:mm] INFO message
```
結論:
1. 使用 Currying 不會失去 function 的功能,一樣可以正常呼叫。
2. 可以輕易的創造需要部分功能先生效的函式。
## 一些需要注意的點:
1. Currying 只能用在參數的數量是固定的情況下,因此像是 f(...args) 的函式是不能操作的!
2. 定義上來說 Currying convert sum(a, b, c) into sum(a)(b)(c) ,不過在大多數情況下,應該可以定義為在複數的參數下還是可以讓 function callable ,不局限於 3 個,只要符合上一點的情況即可。