Skip to content
On this page

Curry Function

커리함수란?

다수의 인자를 한번에 하나씩 받는 함수를 가리키는데 arrow function으로 간결하게 표현할 수 있습니다.

js
// add = a => b => Number
const add = (a) => (b) => a + b;

Point-free Style

커리함수로 인자를 참조하지 않는 정의를 가지는 point-free style 함수를 구현할 수 있습니다.

js
const inc = add(1); // point-free style

inc(3); // => 4

point-free style 함수는 다음과 같은 사용이점들이 있습니다.

  1. generalization

    • 다양한 타입의 데이터를 인자로 전달할 수 있습니다.
  2. specialization

    • 일부 인자를 고정하여 원하는 용도로 범위를 좁힐 수 있어서 function composition을 구현할 수 있습니다.

Utils

커리함수로 구현할 수 있는 util들은 다음과 같습니다.

compose

여러 함수들을 인자로 받아서 대수학의 합성함수를 반환합니다.

js
const compose =
  (...fns) =>
  (x) =>
    fns.reduceRight((y, f) => f(y), x);
// compose(f, g, h)(x) => f(g(h(x)))

pipe

여러 함수들을 인자로 받아서 순서대로 합성하는 함수를 반환합니다.

js
const pipe =
  (...fns) =>
  (x) =>
    fns.reduce((y, f) => f(y), x);
// pipe(f, g, h)(x) => h(g(f(x)))

asyncPipe

일련의 비동기 작업들을 순서대로 처리하는 pipe 함수입니다.

js
const asyncPipe = (...fns) => x => (
	fns.reduce(async (y, f) = > f(await y), x)
);

trace

compose, pipe 함수 내에서 중간에 연산된 값을 고정된 label과 함께 전달합니다.

js
const trace = (label) => (value) => {
  console.log(`${label}: ${value}`);
  return value;
};
js
const g = (n) => n + 1;
const f = (n) => n * 2;

pipe(g, trace("after g"), f, trace("after f"))(20);
/*
after g: 21
after f: 42
*/
compose(trace("after f"), f, trace("after g"), g)(20);
/*
after g: 21
after f: 42
*/

설계방식

커리함수를 정의할 때 “data last” 즉, 최종함수가 받는 인자를 가장 마지막에 전달하는 방식을 권장합니다.

js
const map = (fn) => (mappable) => mappable.map(fn);

const pipe =
  (...fns) =>
  (x) =>
    fns.reduce((y, f) => f(y), x);

const log = (...args) => console.log(...args);

const isEven = (n) => n % 2 === 0;

const stripe = (n) => (isEven(n) ? "dark" : "light");
js
const arr = [1, 2, 3, 4];

const stripeAll = map(stripe);
const striped = stripeAll(arr);

log(striped);
// => ["light", "dark", "light", "dark"]
js
const double = (n) => n * 2;

const doubleAll = map(double);
const doubled = doubleAll(arr);

log(doubled);
// => [2, 4, 6, 8]