본문 바로가기

Study/VanillaJS

[개념잡기] 함수형 프로그래밍 - (5) reduce

[개념잡기] 함수형 프로그래밍 - (5) reduce

함수형 프로그래밍

reduce의 동작원리

이러한 방식으로 동작하는 reduce 함수를 만들어보겠다.

const _reduce = (list, iter, memo) => {}

console.log(_reduce([1, 2, 3], add)) // 6
console.log(_reduce([1, 2, 3], add, 0)) // 6
console.log(_reduce([1, 2, 3], add, 10)) // 16

배열, 함수, 시작값을 인자로 받아 해당 시작값을 기준으로 배열에서 값을 하나씩 꺼내 인자로 받은 함수를 실행하는 reduce 를 만들어 보자.

위 코드를 예시로 들면

console.log(_reduce([1, 2, 3], add, 0)) 

memo = add(0, 1) // 1
memo = add(memo, 2) // 3
memo = add(memo, 3) // 6

return memo

이런 원리로 값을 리턴하는 것이다.

reduce

위에 만들어놓은 함수들을 활용하여 reduce 함수를 구현해보겠다.

const _reduce = (list, iter, memo) => {
  _each(list, (val) => {
    memo = iter(memo, val)
  })
  return memo
}

console.log(_reduce([1, 2, 3], add)) // NaN
console.log(_reduce([1, 2, 3], add, 0)) // 6
console.log(_reduce([1, 2, 3], add, 10)) // 16

인자가 두개일때도 오류없이 동작하게 로직을 구현해보자.
우선 arguments 를 검사하여 2개라면 배열의 첫번째 값을 memo로 저장하고 배열의 두번째 값 부터 함수에 적용하도록 작성하면 되겠다.

const _reduce = function(list, iter, memo) {
  if(arguments.length == 2) {
    [memo, ...list] = list
  }
  _each(list, (val) => {
    memo = iter(memo, val)
  })
  return memo
}

console.log(_reduce([1, 2, 3], add)) // 6
console.log(_reduce([1, 2, 3], add, 0)) // 6
console.log(_reduce([1, 2, 3], add, 10)) // 16

구조분해 할당을 이용하여 memo 와 list를 잘라내었다.

정리

지금까지 작성한 함수들이다.

const _filter = (list, predi) => {
  var new_list = []
  _each(list, (val) => {
    if(predi(val)) {
      new_list.push(val)
    }
  })
  return new_list
}

const _map = (list, mapper) => {
  var new_list = []
  _each(list, (val) => {
    new_list.push(mapper(val))
  })
  return new_list
}

const _each = (list, iter) => {
  for(var i = 0; i < list.length; i++) {
    iter(list[i])
  }
}

const _curry = (fn) => {
  return function (a, b) {
    return arguments.length == 2 ? fn(a,b) : b => fn(a, b)
  }
}

const _curryr = (fn) => {
  return function (a, b) {
    return arguments.length == 2 ? fn(a,b) : b => fn(b, a)
  }
}

const _get = _curryr((obj, key) => {
  return obj == null ? undefined : obj[key]
})

const _reduce = function(list, iter, memo) {
  if(arguments.length == 2) {
    [memo, ...list] = list
  }
  _each(list, (val) => {
    memo = iter(memo, val)
  })
  return memo
}