reducer를 이용한 소프트웨어 합성에 대해 좀 더 알아봅니다.
다음 글의 번역입니다. https://medium.com/javascript-scene/reduce-composing-software-fe22f0c39a1d
What is Reducer?
array.reduce(
reducer: (accumulator: any, current: any) => any,
initialValue: any
) => accumulator: any
[2, 4, 6].reduce((acc, n) => acc + n, 0); // 12
const summingReducer = (acc, n) => acc + n;
[2, 4, 6].reduce(summingReducer, 0); // 12
Reducer는 다재다능 합니다.
리듀서는 다재다능합니다. reduce를 사용하여 map(), filter(), forEach() 및 기타 많은 흥미로운 것들을 정의하는 것은 쉽습니다.Map :
const map = (fn, arr) => arr.reduce((acc, item, index, arr) => {
return acc.concat(fn(item, index, arr));
}, []);
Filter :
const filter = (fn, arr) => arr.reduce((newArr, item) => {
return fn(item) ? newArr.concat([item]) : newArr;
}, []);
Fliter는 조건부 함수를 사용하고
아이템이가 조건부 검사를 통과하면 조건부로 새 배열에 현재 값을 추가한다는 점을 제외하고는
map과 거의 동일한 방식으로 작동합니다.
(fn(item)이 true를 반환함).
Filter는 조건부 함수를 사용하고 항목이 조건부 검사를 통과하면 조건부로 새 배열에 현재 값을 추가한다는 점을 제외하고는
map과 거의 동일한 방식으로 작동합니다(fn(item)이 true를 반환함).
Map, Filter 예시는 데이터 리스트의 항목에 함수를 적용하고 결과를 누적 값으로 접습니다.
하지만 데이터가 함수 목록이라면 어떻게 될까요?
Compose :
Reduce는 함수를 합성하는 편리한 방법이기도 합니다.
함수 합성을 기억하십시오: 함수 f를 x의 결과, 즉 합성 f에 적용하려는 경우 f . g 를 의미합니다.
f(g(x))
Reduce를 사용하면 해당 프로세스를 추상화하여 여러 함수를 합성할 수 있으므로
다음을 나타내는 함수를 쉽게 정의할 수 있습니다.
f(g(h(x)))
그렇게 하려면 reduce를 반대로 실행해야 합니다.
즉, 왼쪽에서 오른쪽이 아니라 오른쪽에서 왼쪽입니다.
고맙게도 JavaScript는 .reduceRight() 메서드를 제공합니다.
Pipe :
compose()는 내부에서 외부로, 즉 수학 표기법 의미에서 컴포지션을 표현하려는 경우에 좋습니다.
그러나 그것을 일련의 사건의 발생 순서로 생각하고 싶다면 어떻게 해야 할까요?
const add1 = n => n + 1;
const double = n => n * 2;
const add1ThenDouble = compose(
double,
add1
);
add1ThenDouble(2); // 6
// ((2 + 1 = 3) * 2 = 6)
문제가 보이시나요?
첫 번째 단계는 마지막에 나열되어 있으므로
함수 실행 순서를 이해하려면 목록의 맨 아래에서 시작하여 맨 위로 뒤로 이동해야 합니다.
const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x);
const add1ThenDouble = pipe(
add1,
double
);add1ThenDouble(2); // 6
// ((2 + 1 = 3) * 2 = 6)
const doubleThenAdd1 = pipe(
double,
add1
);doubleThenAdd1(2); // 5
리덕스에 관하여
Redux는 리듀서 함수를 사용하여 애플리케이션 상태를 관리합니다.
Redux 스타일의 리듀서는 현재 상태와 액션 객체를 가져와서 새로운 상태를 반환합니다.
reducer(state: Any, action: { type: String, payload: Any}) => newState: Any
- 매개변수 없이 호출된 리듀서는 유효한 초기 상태를 반환해야 합니다.
- 리듀서가 액션 타입을 처리하지 않을 경우에도 상태를 반환해야 합니다.
- Redux 리듀서는 순수 함수여야 합니다.
const ADD_VALUE = 'ADD_VALUE';const summingReducer = (state = 0, action = {}) => {
const { type, payload } = action; switch (type) {
case ADD_VALUE:
return state + payload.value;
default: return state;
}
};
const actions = [
{ type: 'ADD_VALUE', payload: { value: 1 } },
{ type: 'ADD_VALUE', payload: { value: 1 } },
{ type: 'ADD_VALUE', payload: { value: 1 } },
];
actions.reduce(summingReducer, 0); // 3
결론 :
'FrontEnd' 카테고리의 다른 글
스토리북 개발팀이 알려주는 컨테이너 / 프리젠터 패턴 - Context API를 이용해 의존성 주입하기 (0) | 2022.09.22 |
---|---|
소프트웨어 합성 : 트랜스듀서(Transducers) (0) | 2022.09.20 |
AST 활용 1편 : ESLint console.log 체크 플러그인 만들기 (0) | 2022.09.19 |
[React] React.cloneElement 사용 사례 (0) | 2022.09.15 |
리액트 디자인 패턴 : 컴파운드 컴포넌트 패턴 [Compound Component Pattern] 2 (0) | 2022.09.15 |