이터러블 프로그래밍 - ChoDragon9/posts GitHub Wiki

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/function*

재귀 함수

range

function range(end, start=0, step=1) {
  if (start > end - 1) {
    return []
  }
  return [start, ...range(end, start+step, step)]
}

range(0) // []
range(3) // [0, 1, 2]

map

function map(fn, [head, ...tail]) {
  if (head === undefined) {
    return []
  }
  return [fn(head), ...map(fn, tail)]
}
map(v => v * 10, [0, 1, 2]) // [0, 10, 20]

지연리스트 재귀 함수

range

function* range(end, start=0, step=1) {
  if (start > end - 1) {
    return
  }
  yield start
  yield* range(end, start+step, step)
}

console.log(...range(4)) // 0 1 2 3

map

function* map(fn, list) {
  const {value, done} = list.next()
  if (done) return
  yield fn(value)
  yield* map(fn, list)
}

console.log(
  ...map(v=>v*10, range(3))
) // 0 10 20 30

filter

function* filter(fn, list) {
  const {value, done} = list.next()
  if (done) return
  if (fn(value)) yield value
  yield* filter(fn, list)
}

console.log(
  ...filter(v=>v>3, range(5))
) // 4 5

지연 함수의 종결 함수

collect

const collect = list => [...list]

reduce

function* reduceLazy(fn, list, acc) {
  const {value, done} = list.next()
  if (done) {
    yield acc
    return
  }
  yield* reduceLazy(fn, list, fn(acc, value))
}

const reduce = (fn, list, acc = []) => {
  const [result] = collect(reduceLazy(fn, list, acc))
  return result
}

console.log(
  reduce(
    (acc, v)=> acc+v,
    range(4),
    0
  )
)

take

function* takeLazy(end, list, start=1) {
  if (start > end) return
  const {value} = list.next()
  yield value
  yield* takeLazy(end, list, start+1)
}

const take = (end, list, start=1) => {
  return collect(takeLazy(end, list, start))
}

console.log(
  take(2, range(4))
) // [0, 1]