# Partial Application

一種減少函式參數個數 Arity 的流程(Arity 指的是形式參數 parameter 的個數)。


試著解釋 Ramda 中 partial 的範例。

const greet = (salutation, title, firstName, lastName) =>
  salutation + ', ' + title + ' ' + firstName + ' ' + lastName + '!';

const sayHello = R.partial(greet, ['Hello']);
const sayHelloToMs = R.partial(sayHello, ['Ms.']);
sayHelloToMs('Jane', 'Jones');
1
2
3
4
5
6

# 拆解步驟

  1. line 4 狀態

    const sayHello = (...args) => greet(['Hello'], ...args);
    
    1
  2. line 5 狀態

    const sayHelloToMs = (...args) => sayHello(['Ms.'], ...args);
    
    1

partial 函式內的實做類似於:

const partial = (fn, ...presetArgs) => (...laterArgs) =>
  fn(...presetArgs, ...laterArgs);
1
2

利用 closure 的概念,保留最一開始的 fn 與參數,後面只要依序傳入參考值即可。

# partial and map

試著將 [30, 55, 42, 87, 66] 每一個值都加上 10

const add = R.curry((x, y) => x + y);
R.map(R.partial(add, [10]), [30, 55, 42, 87, 66]);
1
2

# partialRight

一開始傳入的參數,會從函式的右方 closes over。

const foo = (x, y, z, ...rest) => `${x}${y}${z}${rest}`;

R.partialRight(foo, '在你的右邊')(); // "在你的右,邊"
R.partialRight(foo, '在你的右邊')(1); // "1在你的,右,邊"
R.partialRight(foo, '在你的右邊')(1, 2); // "12在你,的,右,邊"
R.partialRight(foo, '在你的右邊')(1, 2, 3); // "123在,你,的,右,邊"
R.partialRight(foo, '在你的右邊')(1, 2, 3, 4); // "1234,在,你,的,右,邊"
1
2
3
4
5
6
7

# 參數順序調整

當傳入的參數為解構類型時,需做以下的改寫:

function partialProps(fn, presetArgsObj) {
  return function partiallyApplied(laterArgsObj) {
    return fn(Object.assign({}, presetArgsObj, laterArgsObj));
  };
}
1
2
3
4
5
function move({ x = 0, y = 0, z } = {}) {
  return [x, y, z];
}

const f2 = partialProps(move, { y: 2 });
f2({ x: 1, z: 6 }); // [1, 2, 6]
1
2
3
4
5
6

# 參考

Partial Application 偏函式應用 (opens new window)

Last Updated: 2021/2/25 上午8:00:30