지난 주제에 reduce를 소개를 하였다. reduce를 이용하여, map, filter, compose등 여러 함수를 만들 수 있는 것을 볼 수 있었을 것이다.
뭐 눈치는 챘겠지만 함수형 프로그래밍을 공부를 하기 위하여 작성하는 포스팅들이다. 하지만, 지난번에 작성한 reduce는 아쉬운 점이 있다. for문을 사용 하였다는 것이다.
for문이 뭐가 문제인가? 라는 생각을 할 수 있겠지만, 많은 함수형 프로그래밍 언어에서는 for, while ~ do와 같은 장치는 지원하지 않는 다는 것이다. 반복문 없이 코드를 어떻게 작성하냐 싶겠지만, 우리는 모두 안다. 재귀를 사용하면 된다는 것을....
그렇다 이번에는 reduce를 재귀를 이용하여 작성을 해보려고 한다.
reduce 재귀함수 ver.
function reduce( arr, reducer, initValue ) {
if( !arr.length ) return initValue
const currentValue = arr.shift()
initValue = reducer( currentValue, initValue )
return reduce( arr, reducer, initValue )
}
재귀 함수로 코드를 작성하고자 한다면 위와 같이 작성 할 수 있을 것이다.
const arr = [1, 2, 3, 4]
reduce(arr, (c, a) => c + a, 0)
// 10
console.log(arr) // []
정상적으로 잘 작동 하는 듯 하였지만, shift함수를 이용 해버려서 배열의 데이터를 손상 시켰다. 이 부분은 아래와 같이 수정이 가능하다.
function reduce( arr, reducer, initValue ) {
if( !arr.length ) return initValue
const [currentValue, ...others] = arr
initValue = reducer( currentValue, initValue )
return reduce( others, reducer, initValue )
}
우리의 코드는 더욱 견고해졌다. 사실 좀 더 생각 해볼 만한 것이 있다. if문 인데, 하스켈과 같이 좀 더 엄격한 함수형 프로그래밍 언어에는 if문 대신 if 표현식이 있다.
문과 표현식의 차이는 문은 코드들을 덩어리로 묶고, 표현식은 단일 값으로 평가되는 코드 덩어리고 보면 된다.
표현과 문에 대해서 다음 번에 다루기로 하고 if를 삼항 연산자로 바꾸고 싶다는 뜻으로 해석 하면 된다. 그 결과는 아래와 같다.
function reduce( arr, reducer, initValue ) {
const [currentValue, ...others] = arr
return arr.length ?
reduce( others, reducer, reducer( currentValue, initValue ) ) :
initValue
}
참고
문제는 위와 같은 방법으로 구현을 한다면 아래와 같은 에러를 볼 수 있을 것이다.
Uncaught RangeError: Maximum call stack size exceeded
따라서 위와 같이 for문 if문 없이 reduce를 작성 할 수 있고, 그것을 이용해서 함수형 프로그래밍을 할 때 사용할 함수들을 구현 할 수 있다. 이 정도만 알아 두도록 하자.
댓글
댓글 쓰기