이 글은 유인동님의 함수형 프로그래밍 강의내용을 정리한 글입니다.
이터레이터이자 이터러블을 생성하는 함수
즉, 제너레이터는 이터레이터를 리턴하는 함수이다.
제너레이터는 순회할 값을 문장으로 표현한는 것이다.
제너레이터는 함수명앞에 *
키워드를 사용해서 선언한다.
제너레이터의 yield
를 통해서 이터레이터의 next()
메서드 리턴값인 { value, done }
객체를 초기화할 수 있다. (값을 설정할 수 있다.)
또한 리턴값을 지정할 수 있지만 순회에 참조되지는 않는다.
function* generator() {
yield 1;
if (false) yield 2;
yield 3;
return 100; // 이터레이터.next() 마지막 리턴값 {value: 100, done: true}
}
let iterator = generator(); // 제너레이터의 실행결과는 이터레이터이다.
log(iterator[Symbol.iterator] == iterator);
// 이터레이터는 이터레이터이자 이터러블이다.
// 이터레이터의 이터레이터는 자기자신이다.
log(iterator.next()); // {value: 1, done: false}
log(iterator.next()); // {value: 3, done: false}
log(iterator.next()); // {value: 100, done: true}, 순회에 참조 되지는 않는다.
log(iterator.next()); // {value: undefined, done: true}
for (const a of gen()) log(a); // 제너레이터의 결과가 이터레이터이기 때문에 순회가 가능하다.
// 1
// 3
제너레이터는 직관적인 문장으로 순회할 수 있는 값(이터러블)을 만들수 있다.
이 말은 문장을 이터러블로 만들수 있다는 뜻이기도 하다.
자바스크립트는 이런 제너레이터를 통해서 어떠한 상태나 어떠한 값이든 순회할 수 있는 형태인 이터러블로 만들수 있다.
제너레이터에서 문장과 로직을 통해 값을 발생시키는 것을 제어할 수 있다.
function* odds(max){
for (let i = 0; i <= max;, i++) {
if (i % 2) yield i;
}
}
let iter = odds(5);
log(iter.next()); // {value: 1, done: false}
log(iter.next()); // {value: 3, done: false}
log(iter.next()); // {value: 5, done: false}
log(iter.next()); // {value: undefined, done: true}
function* inifinity() {
while (true) yield i++;
}
let iter = inifinity();
log(iter.next()); // {value: 1, done: false}
log(iter.next()); // {value: 2, done: false}
log(iter.next()); // {value: 3, done: false}
.
.
.
무한히 값을 생성하지만 이터레이터의 next()
를 평가할 때만 동작하기 때문에 브라우저나 프로그램이 멈추지는 않는다.
function* inifinity(i = 0) {
while (true) yield i++;
}
function* limit(l, iter) {
for (const a of iter) {
yield a;
if (a == l) return;
}
}
function* odds(l) {
for (const a of limit(l, inifinity(1))) {
if (a % 2) yield a;
}
}
for (const a of odds(40)) console.log(a);
// 1
// 3
// 5
// ...
// 37
// 39
다양한 로직의 문장으로 순회할 수 있는 값을 만들 수 있다.
제너레이터는 이터러블 프로토콜을 따른다. 따라서 이터러블 프로토콜을 따르는 문법, 라이브러리, 함수 등과 함께 활용할 수 있다.
log(...odds(10));
// 1 3 5 7 9
log([...odds(10), ...odds(20)]);
// [1, 3, 5, 7, 9, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
const [head, ...tail] = odds(5);
log(head); // 1
log(tail); // [3, 5]
const [a, b, ...rest] = odds(10);
log(a); // 1
log(b); // 3
log(rest); // [5, 7, 9]