함수형 프로그래밍의 필수개념인 generator에 대해 알아보았다.
generator generator는 iterator이자 iterable을 생성하는 함수이다.
함수를 선언할 때 함수명 앞에 *
를 붙여 만든다 yield를 통해 iterator를 반환한다. generator를 이용하며 어떤 값이든 순회할 수 있는 형태로 작성할 수 있다. generator 내부 반환되는 값은 done:true
일 때의 value로 반환된다. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 function * gen ( ) { yield 1 ; if (false ) yield 4 ; yield 2 ; yield 3 ; return 100 ; } let iter = gen();console .log(iter[Symbol .iterator]() == iter); console .log(iter.next()); console .log(iter.next()); console .log(iter.next()); console .log(iter.next()); for (const a of gen()) console .log(a);
generator를 작성하는 여러가지 방법 아래의 oods 함수는 홀수를 value로 하는 iterable을 반환하는 generator이다.
1 2 3 4 5 6 7 8 9 10 11 function * oods ( ) { yield 1 ; yield 3 ; yield 5 ; } let iter2 = oods();console .log(iter2.next()); console .log(iter2.next()); console .log(iter2.next()); console .log(iter2.next());
generator는 for문을 이용하여 작성할 수 있다.
1 2 3 4 5 6 7 8 9 10 function * oods (l ) { for (let i = 0 ; i < l; i++) { if (i % 2 ) yield i; } } let iter2 = oods(6 );console .log(iter2.next()); console .log(iter2.next()); console .log(iter2.next()); console .log(iter2.next());
또한 generator는 while을 이용하여 작성할 수 있다.
아래의 infinity는 무한수열을 만드는 generator이고 limit 함수는 l까지는 a를 yield하다가 l이 될 경우 return 하는 generator이다. infinity generator와 limit generator를 이용하여 odds generator도 새로 정의하였다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 function * infinity (i = 0 ) { while (true ) yield i++; } function * limit (l, iter ) { for (const a of iter) { yield a; if (a == l) return ; } } function * oods (l ) { for (const a of limit(l, infinity(1 ))) { if (a % 2 ) yield a; } } let iter4 = oods(6 );iter3.next(); iter3.next(); iter3.next(); iter3.next(); for (const a of oods(6 )) console .log(a);
iterable/iterator 프로토콜 generator는 iterable/iterator 프로토콜을 따르고 있기 떄문에 iterable/iterator 프로토콜을 따르는 여러 연산이나 함수들을 적용할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 function * infinity (i = 0 ) { while (true ) yield i++; } function * limit (l, iter ) { for (const a of iter) { yield a; if (a == l) return ; } } function * oods (l ) { for (const a of limit(l, infinity(1 ))) { if (a % 2 ) yield a; } } console .log(...odds(10 ));console .log([...oods(10 ), ...oods(20 )]);const [head, ...tail] = oods(5 );console .log(head);console .log(tail);const [a, b, ...rest] = oods(10 );console .log(a);console .log(b);console .log(rest);
Ref 함수형 프로그래밍과 JavaScript ES6+