본문 바로가기

Study/Today I Learn

[TIL] 2019.03.24

Generator

well-formed iterator를 리턴하는, iterable을 생성하는 함수
함수앞에 * 을 붙여 만들고, yield 를 통하여 몇번의 next 로 값을 꺼내줄지 결정
return 값을 줄 수 있음, 하지만 return 값을 순회에 영향을 주지 못함

function *gen () {
  yield 1
  yield 2
  yield 3

  return 100
}

let iter = gen()
let iter2 = gen()

log(iter == iter[Symbol.iterator]())

for(const a of iter) log(a)

log(iter2.next()) // {value: 1, done: false}
log(iter2.next()) // {value: 2, done: false}
log(iter2.next()) // {value: 3, done: false}
log(iter2.next()) // {value: 100, done: true}

generator의 이점

자바스크립트에서 모든 iterable은 순회가 가능하다. generator는 iterable 을 생성하는 함수이므로 generator 를 이용하면 거의 모든 값들을 순회가능 하도록 만들수 있다.

Generator 활용

짝수 걸러내기

function *infinity(i = 0) {
  while(1) yield i++
}

function *limit(l, iter) {
  for(const a of iter) {
    yield a
    if(a == l) return
  }
}

function *even(l = 1){
  for(const a of limit(l, infinity(1))){
    if(!(a % 2)) yield a
  }
}

for(const a of even(8)) log(a)
// 2 4 6 8

map

const map = (f, iter) => {
  let res = []
  for(const a of iter) {
    res.push(f(a))
  }
  return res
}

log(map(v => v * 2, [1, 2, 3, 4])) // [2, 4, 6, 8]

filter

const filter = (f, iter) => {
  let res = []
  for(const a of iter) {
    if(f(a)) res.push(a)
  }
  return res
}

log(filter(v => v % 2, function *(){
  yield 1
  yield 2
  yield 3
} ())) // [1, 3]

reduce

const reduce = (f, acc ,iter) => {
  if(!iter) {
    iter = acc[Symbol.iterator]()
    acc = iter.next().value
  }
  for(const a of iter) {
    acc = f(acc, a)
  }
  return acc
}

log(reduce((a, b) => a + b, 0, [1, 2, 3, 4])) // 10
log(reduce((a, b) => a + b, [1, 2, 3, 4])) // 10

go

const go = (...args) => reduce((a, f) => f(a), args)

go(
    0,
    a => a+1,
    a => a+10,
    a => a+100,
    log
) // 111

pipe

const pipe = (f, ...fs) => (...args) => go(f(...args), ...fs)

et f1 = pipe(
  (a, b) => a + b,
  a => a + 1,
  log,
)

let f2 = pipe(
  a => a + 1,
  a => a + 10,
  log,
)

f1(1, 2) // 4
f2(1) // 12

'Study > Today I Learn' 카테고리의 다른 글

[TIL] 2019.04.01  (0) 2019.04.01
[TIL] 2019.03.30  (0) 2019.03.30
[TIL] 2019.03.22  (0) 2019.03.23
[TIL] 2019.03.21  (0) 2019.03.22
[TIL] 2019.03.20  (0) 2019.03.20