JavaScript/함수형 프로그래밍과 JavaScript ES6+

제너레이터와 이터레이터

느리지만 꾸준하게 2021. 8. 17. 18:16

제너레이터는 이터레이터이자 이터러블을 생성하는 함수를 말한다. 즉 이터레이터를 리턴하는 함수이다.

제너레이터는 일반함수에서 앞에 *을 붙여서 제너레이터 함수를 만든다. 또 제너레이터는 이터레이터를 반환한다.

 

아래와 같이 제너레이터가 있다고 했을 때 제너레이터를 실행한 결과는 이터레이터이다. 이터레이터를 아래코드와 같이 실행 해보자. 제너레이터를 통해 쉽게 이터레이터를 만들 수 있다.

<script>
    function* gen() {
        yield 1;
        yield 2;
        yield 3;
    }
    let iter = gen();
    log(iter.next());
    log(iter.next());
    log(iter.next());
    log(iter.next());
</script>

=>

{value: 1, done: false}
index.html:14 {value: 2, done: false}
index.html:15 {value: 3, done: false}
index.html:16 {value: undefined, done: true}

이터레이터이자 이터러블이기도 한데 이터레이터는 심볼 이터레이터를 가지고 있고 심볼 이터레이터의 실행결과는 자기자신이다. 그러니까 제너레이터는 well-formed 이터레이터를 리턴하는 함수이다. 그리고 제너레이터의 yield를 통해서 몇 번의 next를 통해 값을 꺼내줄 것인지를 정할 수 있다. 

    let iter = gen();
    log(iter[Symbol.iterator]() == iter);
    log(iter.next());
    log(iter.next());
    log(iter.next());
    log(iter.next());
    
    =>
    
    true
index.html:14 {value: 1, done: false}
index.html:15 {value: 2, done: false}
index.html:16 {value: 3, done: false}
index.html:17 {value: undefined, done: true}

그리고 제너레이터를 사용하게 되면 역시 제너레이터의 실행결과가 이터러블이자 이터레이터이기 때문에 아래와 같이 순회를 할 수 있다. 

    let iter = gen();
    log(iter[Symbol.iterator]() == iter);
    log(iter.next());
    log(iter.next());
    log(iter.next());
    log(iter.next());

    for (const a of gen()) log(a);



=>

true
index.html:14 {value: 1, done: false}
index.html:15 {value: 2, done: false}
index.html:16 {value: 3, done: false}
index.html:17 {value: undefined, done: true}
index.html:19 1
index.html:19 2
index.html:19 3

그리고 제너레이터에서는 마지막에 리턴값을 만들 수 있다.

조심할 것은 순회할 때 리턴값은 제외하고 순회가 이루어진다. 리턴 값은 마지막에 done 할때 나오는 값이라고 생각하자.

<script>
    function* gen() {
        yield 1;
        yield 2;
        yield 3;
        return 100;
    }
    let iter = gen();
    log(iter[Symbol.iterator]() == iter);
    log(iter.next());
    log(iter.next());
    log(iter.next());
    log(iter.next());

    for (const a of gen()) log(a);
</script>

=>

true
index.html:15 {value: 1, done: false}
index.html:16 {value: 2, done: false}
index.html:17 {value: 3, done: false}
index.html:18 {value: 100, done: true}
index.html:20 1
index.html:20 2
index.html:20 3

그리고 제너레이터는 순회할 값을 문장으로 표현하는 것이라고도 할 수 있다. 그래서 아래코드를 작성하면 순회가 이루어지는 함수를 만들 수 있다. 자바스크립트에서는 어떠한 값이든 이터러블이면 순회할 수 있다.

그런데 제너레이터는 이런 문장을 값으로 만들 수 있고 문장을 통해서 순회할 수 있는 값을 만들 수 있기 때문에 자바스크립트에서는 제너레이터를 통해서 어떠한 상태나 어떠한 값이든 사실상 순회할 수 있게 만들 수 있다. 

 

굉장히 상징적이다. 

 

제너레이터라는 문장을 통해 순회할 수 값을 만들 수 있다는 것은 어떠한 값도 순회할 수 있는 형태로 제너레이터라는 문장을 통해 조작할 수 있으며 제너레이터를 통해서 굉장히 다양한 값들을 순회할 수 있는 이터러블을 쉽게 그리고 프로그래머가 로직을 만들면서 순회를 시킬 수 있다는 것이다.

<script>
    function* gen() {
        yield 1;
        if (false) yield 2;
        yield 3;
    }
    let iter = gen();
    log(iter[Symbol.iterator]() == iter);
    log(iter.next());
    log(iter.next());
    log(iter.next());
    log(iter.next());

    for (const a of gen()) log(a);
</script>

=>

true
index.html:14 {value: 1, done: false}
index.html:15 {value: 3, done: false}
index.html:16 {value: undefined, done: true}
index.html:17 {value: undefined, done: true}
index.html:19 1
index.html:19 3

 

 

 

 

 

 

 

 

 

<출처 : 유인동 함수형 프로그래밍과 JavaScript ES6+>

https://www.inflearn.com/course/functional-es6/dashboard

 

함수형 프로그래밍과 JavaScript ES6+ - 인프런 | 강의

ES6+와 함수형 프로그래밍을 배울 수 있는 강의입니다. 이 강좌에서는 ES6+의 이터러블/이터레이터/제너레이터 프로토콜을 상세히 다루고 응용합니다. 이터러블을 기반으로한 함수형 프로그래밍,

www.inflearn.com