https://daunje0.tistory.com/174
위 블로그에서 계속 됩니다.
const log = console.log
const products = [
{name: '반팔티', price: 15000},
{name: '긴팔티', price: 20000},
{name: '핸드폰케이스', price: 15000},
{name: '후드티', price: 30000},
{name: '바지', price: 25000}
];
const go = (...args) => args.reduce((a, f) => f(a));
const add = (a,b) => a+ b
log(
products
.filter(p => p.price < 20000)
.map(p => p.price)
.reduce(add)
) //30000
앞에서 다룬 go 함수를 활용하면 가독성 높은 map. filter, reduce를 만들 수 있습니다.
go(
products,
products => products.filter(p => p.price < 20000),
products => products.map(p => p.price),
prices => prices.reduce(add),
log
) // 30000
물론 이런 식의 사용도 가능합니다.
const log = console.log
const add = (a, b) => a + b;
const go = (...args) => args.reduce((a, f) => f(a));
const filter = f => products => products.filter(f);
const map = f => products => products.map(f);
const reduce = f => prices => prices.reduce(f);
go(
products,
filter(p => p.price < 20000),
map(p => p.price),
reduce(add),
log
) // 30000
다음 다룰 사용자 정의 함수 curry 는 이 글의 제목처럼 함수의 부분 적용과 유연한 합성이 특징입니다
const curry = f =>
(a, ..._) =>_.length ? f(a, ..._) : (..._) => f(a, ..._)
// 1. 인자로 함수를 받아 함수를 리턴한다
// 2. 리턴된 함수가 실행 될 때, 인자가 2개 이상이면 받아 둔 f(a, ..._)함수를 즉시 실행
// (인자에서 전개연산자를 쓰면 배열화 되는 데, _의 길이가 1 이상이면 a와 함께 인자가 2개 이상이란 뜻이 된다)
// 3. 1개만 인자가 있으면 , 새로 받은 인자 a 를 가지고 있다가 이후에 받은 ..._ 인자들과 함께 f(a, ..._) 를 실행한다
// 4. 특정 값을 지닌 함수를 먼저 만들어 놓고 이후 실행시 값을 리턴하는 패턴
// 예시
const multiply = curry((a, b) => a * b)
log('multiply::', multiply(1)(2)) // multiply:: 2
const mult5 = multiply(5)
log(mult5(1)) // 5
log(mult5(2)) // 10
log(mult5(3)) // 15
go(
products,
products => products.filter(p => p.price < 20000),
products => products.map(p => p.price),
prices => prices.reduce(add),
log
) // 30000
이 코드에 curry 를 적용한다면 아래와 같습니다
const log = console.log
const add = (a, b) => a + b;
const go = (...args) => args.reduce((a, f) => f(a));
const curry = f =>
(a, ..._) =>_.length ? f(a, ..._) : (..._) => f(a, ..._)
const filter = curry((f, iter) => iter.filter(f));
const map = curry((f, iter) => iter.map(f));
const reduce = curry((f, iter) => iter.reduce(f));
go(
products,
filter(p => p.price < 20000),
map(p => p.price),
reduce(add),
log
);
그럼 기존 코드와 curry 적용한 코드의 차이점은 뭘까?
- 유연성
before: 각 함수가 정확히 두 개의 인자를 받도록 고정되어 있습니다.
after: 함수의 인자 개수에 상관없이 유연하게 사용할 수 있습니다. - 부분 적용
before : 부분 적용이 가능하지만, 첫 번째 인자만 부분 적용할 수 있습니다.
after : 어떤 인자든 부분 적용이 가능하며, 여러 단계로 나누어 적용할 수 있습니다. - 재사용성
before: 특정 상황에 최적화되어 있어 다른 상황에서 재사용하기 어려울 수 있습니다.
after : 다양한 상황에서 더 쉽게 재사용할 수 있습니다. 함수들이 더 일반적이어서 다양한 데이터 구조에 사용할 수 있습니다. - 가독성
before : 간단하고 직관적일 수 있지만, 복잡한 로직에서는 중첩된 함수 호출로 인해 가독성이 떨어질 수 있습니다.
after : 처음에는 복잡해 보일 수 있지만, 익숙해지면 더 간결하고 표현력이 풍부해집니다. - 함수 합성
before : 함수 합성이 제한적입니다.
after : 함수들을 더 쉽게 조합하고 재사용할 수 있어 복잡한 로직을 구현하기 쉽습니다.
요약하자면 curry를 사용해야 하는 이유는 다음과 같습니다.
- 더 큰 유연성: 함수를 다양한 방식으로 호출하고 조합할 수 있습니다.
- 향상된 부분 적용: 어떤 인자든 부분적으로 적용할 수 있어 함수의 특수화가 쉽습니다.
- 높은 재사용성: 더 일반적인 함수를 만들어 다양한 상황에서 사용할 수 있습니다.
- 포인트-프리 스타일: 불필요한 인자 전달을 줄여 코드를 더 간결하게 만들 수 있습니다.
'JavaScript > AboutJS' 카테고리의 다른 글
[javascript] FormData form 태그 안의 복수의 input 창 입력값을 한번에 추출하기 (0) | 2024.11.05 |
---|---|
[javascript] 내 위치의 경도, 위도 정보 알아보기 (navigator.geolocation.getCurrentPosition) (0) | 2024.10.24 |
[JavsScript] 함수의 합성과 데이터 파이프라인 2: pipe - 재사용 가능한 함수 파이프라인 만들기 (0) | 2024.10.11 |
[JavsScript] 함수의 합성과 데이터 파이프 라인 1. go - 즉시 실행되는 함수 체인 만들기 (0) | 2024.10.11 |
[JavsScript] yield* 란? (0) | 2024.09.29 |