함수형 프로그래밍(제너레이터 예제)

제너레이터 예제

1. 목표 제너레이터( 홀수만 리턴하는 제너레이터 )

const log = console.log
function *odd(){
  yield 1
  yield 3
  yield 5
}

let iter = odd()
log(iter.next()) // {value : 1, done : false}
log(iter.next()) // {value : 3, done : false}
log(iter.next()) // {value : 5, done : false}
log(iter.next()) // {done : true}

2. 제너레이터 함수의 파라미터로 limit 값 설정

const log = console.log
function *odd(limit){
 	for(let i=0; i<limit; i++){
    if(i%2) yield i
  }
}

let iter = odd(6)
log(iter.next()) // {value : 1, done : false}
log(iter.next()) // {value : 3, done : false}
log(iter.next()) // {value : 5, done : false}
log(iter.next()) // {done : true}

제너레이터를 하나만 사용 했지만 더 많은 제너레이터를 함께 사용 해보자.

3. Infinity 제너레이터 생성

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

infinity 제너레이터는 파라미터로 받은 값이 없다면 0 있다면 그 값 부터 무한히 값을 yield하는 제너레이터다.

let iter2 = infinity()
log(iter2.next()) // {value : 0, done : false}
log(iter2.next()) // {value : 2, done : false}
log(iter2.next()) // {value : 3, done : false}
log(iter2.next()) // {value : 4, done : false}
log(iter2.next()) // {value : 5, done : false}
log(iter2.next()) // {value : 6, done : false}
log(iter2.next()) // {value : 7, done : false}
...

이 제너레이터에 의해 만들어진 이터레이터는 무한히 값을 yield 할 수 있지만 next() 함수로 값이 평가 되야만 yield하기 때문에 브라우저나 프로그램이 멈추지 않는다. ( 무한수열 표현 가능하다. )

4. odd 제너레이터에 infinity 제너레이터 추가

function *infinity(i=0){
  while(true) yield i++
}
function *odd(limit){
  for(const a of infinity(1)){
    if(a % 2) yield a
    if(a === limit) return
  }
}

let iter = odd(10)
log(iter.next()) // {value : 1, done : false}
log(iter.next()) // {value : 3, done : false}
...

5. limit을 담당하는 제너레이터 생성

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

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

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

let iter = odd(10)
log(iter.next()) // {value : 1, done : false}
log(iter.next()) // {value : 3, done : false}
...

for(const a of odd(40)) log(a) // 1 ~ 40 홀수 출력

참고 ) 제너레이터와 이터러블 이터레이터 프로토콜

제너레이터도 이터러블 이터레이터 프로토콜을 따르기 때문에 for..of문, 전개연산자, 구조분해, 나머지 연산자 등을 사용할 수 있다.

log(...odd(10)) // 1 3 5 7 9
log([...odd(10)]) // [1,3,5,7,9]
log([...odd(10), ...odd(20)]) // [1,3,5,7,9,1,3,5,7,9,11,13,15,17,19]

const [ head , ...tail] = odd(10)
log(head) // 1
log(tail) // [3,5,7,9]
const [a, b, ...rest] = odd(10)
log(a) // 1
log(b) // 3
log(rest) // [5,7,9]

Written by@[HongDongUk]
공부한 것을 소소하게 적는 블로그.

GitHubFacebook