-
monad
-
pipe
- I’ve used the pipe() function 2,560 times and I can tell you it’s good! – Obvibase under the hood5
- Hack Pipe for Functional Programmers: How I learned to stop worrying and love the placeholder6
- A quick introduction to pipe() and compose() in JavaScript | by Yazeed Bzadough | We’ve moved to freeCodeCamp.org/news | Medium7
-
hoc
Footnotes
-
Jotai 의
atom((get) => …)이async/await와 같은 모양인 건 우연이 아니다 — atom 과 Promise 가 둘 다 모나드라 같은 do-notation 을 쓴다. 모나드는of·map·join셋을 구현할 수 있는 구조. ↩ -
타입·범주론 없이 모나드를 “발명”해 보는 글. null 체크 조건문을 없애려고
whenExists체이너를 만들다가, 체이너를 돌려주는 함수끼리 이으려니 중첩이 생기고 그걸 펴는 과정에서 모나드가 나온다. ↩ -
2013년 콜백 지옥에서 출발해 Promise·배열의 공통 패턴을 뽑아 Functor → Monad 로 가는 TypeScript 글. async/await 가 모나드 위에 지은 문법이라는 데까지 간다(보너스로 Monoid). ↩
-
Studying With Alex 채널의 모나드 입문 영상. ↩
-
pipe(x, a, b)를 2,560번 쓴 회고.b(a(x))를 왼쪽에서 오른쪽으로 읽게 하는 함수(reduce한 줄)이고, 함수를 합성만 하는compose보다 고차 함수로 생각할 필요가 없어 읽기 쉽다 — 메서드 체이닝을 네이티브 메서드 밖으로 넓힌 것. ↩ -
파이프 연산자
|>제안에 4년 관여한 저자가 F# 파이프 지지에서 Hack 파이프(플레이스홀더)로 돌아선 이유. Hack 파이프가 커링 없이도 쓸 수 있어 함수형 라이브러리와 일반 JS 사이를 잇는다는 주장. ↩ -
pipe는 함수 n 개를 왼쪽→오른쪽으로,compose는 오른쪽→왼쪽으로 잇는다는 입문 (freeCodeCamp 로 옮겨진 글). ↩ -
고차 함수 입문. 함수가 값(일급 시민)이라 인자로 넘기고 돌려줄 수 있고, 그게 DOM 조작 같은 실무 코드에서 왜 쓸모 있는지 예제로 보인다. ↩
/**
* - 인자 수 확인: `curry` 함수는 전달된 함수 `fn`의 인자 수를 확인
* - 인자 수가 충분한 경우: 만약 `args`의 길이가 `fn`의 인자 수 이상이면, `fn`을 호출하고 결과를 반환
* - 인자 수가 부족한 경우: 그렇지 않으면 추가 인자(`moreArgs`)를 받을 수 있는 새 함수를 반환. 이 함수는 기존 인자(`args`)와 새로운 인자(`moreArgs`)를 합쳐 다시 `curry(fn)`을 호출하여 최종적으로 인자가 충분할 때까지 이 과정을 반복
*/
const curry =
(fn: Function) =>
(...args: any[]) =>
args.length >= fn.length
? fn(...args)
: (...moreArgs: any[]) => curry(fn)(...args, ...moreArgs)
/**
* - `...fns: Function[]` 여러 개의 함수를 인자로 받는다
* - 내부에서 `reduce` 메서드를 사용하여 함수 배열을 순회 초기값으로 `x`를 사용하며, 각 함수 `fn`을 차례로 호출하여 결과를 다음 함수로 전달
*/
const pipe =
(...fns: Function[]) =>
(x: any) =>
fns.reduce((acc, fn) => fn(acc), x)
/**
* - `...fns`: 여러 개의 함수를 매개변수로 받음
* - `(x)`: 초기값 `x`를 인자로 받아 결과를 리턴
* - `fns.reduceRight(...)`: 배열의 오른쪽부터 왼쪽으로 각 함수를 적용합니다. `y`는 이전 함수의 결과이며, `f`는 현재 함수
* - `f(y)`: 현재 함수 `f`를 이전 함수의 결과 `y`에 적용
*/
const compose =
(...fns) =>
(x) =>
fns.reduceRight((y, f) => f(y), x)
- 함수 조합(Composition): 작은 함수들을 조합하여 새로운 함수를 만들며, 예를 들어
compose(f, g, h)는f(g(h(x)))로 실행 compose: 오른쪽에서 왼쪽으로 함수를 실행하며,compose(square, double)(3)은 36을 반환pipe: 왼쪽에서 오른쪽으로 함수를 실행하여,pipe(double, square)(3)의 결과는 36- 커링(Currying):
f(a, b, c)를f(a)(b)(c)형태로 변환하고, 예를 들어add(1)(2)(3)의 결과는 61 - 부분 적용(Partial Application): 일부 인자만 미리 적용하여 새로운 함수를 만들 수 있으며,
const double = multiply(2, _)로 정의 - 포인트-프리 스타일: 변수를 사용하지 않고 함수를 조합하여 작성하며, 예를 들면
compose(square, double)와 같은 형태 - 데이터 마지막 원칙(Data Last): 데이터를 마지막 인자로 배치하여 조합성을 높이는데, 예를 들어
const halve = divideDataLast(2)와 같이 사용
- Higher-Order Functions
- How to compose JavaScript functions that take multiple parameters (the epic guide)
- JavaScript function composition: What’s the big deal?
Footnotes
-
Function: length - MDN: “The
lengthdata property of aFunctioninstance indicates the number of parameters expected by the function.” ↩