使用 Currying 就像還貸款一樣,可以慢慢還,不用一口氣還完。也就是說,呼叫函式時,不用一次給足所有的參數,可以一個一個慢慢給。
記得第一次使用到這個技巧的時候是在寫 Scala 的時候,當時一開始不太理解為何要這樣用,但用了一陣子之後就發現這個 Currying 實在是相當好用,因為它可以簡化參數的處理過程,大大的提高了程式碼的彈性、可測試性和可讀性。
舉個例子來說,假設我有一個函式必須要傳入三個參數,第一個是 instance,第二個是 url,第三個是其他參數。那麼我們每次在使用這個函式時就必須得帶入這三個參數,使用起來就會有那麼一點不太方便。這時候我們就可以使用 Currying 將這個函式帶入第一個參數 instance 得到 函式1,那麼我就可以重複利用 函式1 來操作,每次只要帶入兩個參數即可。
又假設,如果我們的 URL 又是相同的,我們就可以將 函式1 帶入 URL 這個參數並且得到 函式2,那我們又可以重複使用 函式2 並帶入不同的其他參數來使用。這樣一來對於冗長的程式碼、需要客製化的 函式 處理有很大的幫助。
在 JavaScript 寫起來可能會有點複雜,但是在 TypeScript 裡寫起來就簡單需多,他的語法是:
let function_name = (param1:type) => (param2:type) => ... => (paramN) => {
// process param and return result
}
以剛剛描述中的例子可以寫成這樣:
let queryData = (connection: string) => (url: string) =>
(method: string) => (parameter: string) => {
console.log("Use Connection: " + connection +
", connect to " + url +
" with method " + method +
" and parameter:" + parameter);
}
let a = queryData("SuperConnection");
let b = a("MY_URL");
let c = b("GET");
c("data=123");
c("data=456");
queryData 如果改用 JavaScript 寫就會像這樣,也就是除非給到最後一個參數,不然每次都是會回傳一個新的函式加上我們給的參數。
var queryData = function(connection) {
return function(url) {
return function(method) {
return function(parameter) {
console.log("Use Connection: " + connection +
", connect to " + url +
" with method " + method +
" and parameter:" + parameter);
};
};
};
};
執行上面那段範例後,會有這樣的結果:
Use Connection: SuperConnection, connect to MY_URL with method GET and parameter:data=123
Use Connection: SuperConnection, connect to MY_URL with method GET and parameter:data=456
這樣我們在重複使用 c
的時候不就是簡潔很多呢!