跳至主要内容

[JS] Functional Programming and Currying

Understanding Currying in JavaScript

Functional Programming 是一種程式撰寫的風格,會把函式當成參數傳入,並以沒有 side effect 的方式回傳另一個函式。這也衍伸了一些概念:

  • Pure Function
  • Currying
  • Higher-Order Function

什麼是 Pure Function

Pure function 有兩個明確的定義:

  1. 當帶入相同的參數時,一定會得到相同的結果,又稱作 deterministic
  2. 它不會造成任何可觀察到的副作用(observable side effects),所有的變數多是 immutable 的。

當一個函式是 pure functionimmutable data,那麼我們可以稱作 referential transparency

immutability 指的是不會隨著時間改變。

什麼是 Currying

Currying 是 functional programming 中的一種過程,我們會將函式當成參數帶入另一個函式的參數中,因此變成嵌套的函式(nesting functions),而這個函式會回傳一個新的函式。

在 Currying 中,會把帶有多個參數(arity)的函式,轉換成一次帶一個參數的多個連續函式。

// 2-arity function
function fn(a, b) {
//...
}

// 3-arity function
function _fn(a, b, c) {
//...

arity:指的是一個函式有的參數數目,近似 arguments

將一般的函式轉成 Currying function:

// 原本的函式帶有三個 arity
function multiply(a, b, c) {
return a * b * c;
}

multiply(1, 2, 3); // 6

轉成 currying function 後:

const multiply = (a) => (b) => (c) => {
return a * b * c;
};

multiply(1)(2)(3); // 6

// 等同於下面的寫法
function multiply(a) {
return function (b) {
return function (c) {
return a * b * c;
};
};
}

currying 背後的概念就是根據一個函式產生一個加料後的函式(specialized function)。

什麼是 Partial Function Application

在 currying 中,每一個函式都只會接收一個參數但在 partial function application 中,一個函式可能會接收超過一個以上的參數

// Partial Function Application
const volume = (h) => (w, l) => {
return h * w * l;
};

console.log(volume(70)(90, 30));

partial applicationcurrying 是相關的,但設計邏輯上並不一樣,兩者一樣的地方在於,它們都依賴閉包(closure)才能作用。

Currying 的好處

為某一個函式設定設置

例如,我們有一個計算折扣的函式,在還沒使用 currying 之前,可以寫成這樣:

function getDiscountPrice(price, discount) {
return price * discount;
}

let price = getDiscountPrice(100, 0.9);

這個的麻煩之處在於,即時全館 9 折,但我們在使用這個函式時每次都還是要把 discount 代到參數中。如果我們使用 currying 則可以制定一個專門就是 9 折用的函式:

const getDiscountPrice = (discount) => (price) => {
return price * discount;
};

// 都是九折的情況
const get10PercentOff = getDiscountPrice(0.9);
let price = get10PercentOff(100); // 90

Higher Order Function

當我們談到 higher-order functions 時,我們指的是:

  • 接受一個以上的函式當作參數
  • 最後會回傳出一個函式

參考