# 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 個,只要符合上一點的情況即可。