본 시리즈는 인프런 강의 함수형 프로그래밍과 JavaScript ES6+ ( 지식 공유자 : 유인동 님 ) 의 강의를 수강하면서 내용을 제 방식대로 포스팅하는 글입니다.
제너레이터를 활용해 홀수만 계속해 발생시키는 이터레이터를 만들어서 순회하는 함수를 만들어보자
function* odds() {
yield 1;
yield 3;
yield 5;
yield 7;
}
let iter2 = odds();
console.log(iter2.next()); // {value: 1, done: false}
console.log(iter2.next()); // {value: 3, done: false}
console.log(iter2.next()); // {value: 5, done: false}
console.log(iter2.next()); // {value: 7, done: false}
console.log(iter2.next()); // {value: undefined, done: true}
... 이렇게 코드를 작성하면 알고리즘 따윈 하나 없는 코드가 ... 된다
물론 우리가 구현하려는 함수가 이런식으로 작동해야한다는 예제가 될수 있다.
이것을 자동화 해보자
// limit 값을 인자로 받은 것이다.
// 2씩 증가하도록 하는것이 더 효율적 이지만, 지금은 제너레이터의 사용법에 좀더 집중해보자
// 제너레이터 내부에서 어떠한 로직으로 값을 발생시키는 것을 제어할수가 있다
function* odds(limit: number) {
for (let i = 0; i < limit; i++) {
if (i % 2) yield i;
}
}
let iter2 = odds(10);
console.log(iter2.next()); // {value: 1, done: false}
console.log(iter2.next()); // {value: 3, done: false}
console.log(iter2.next()); // {value: 5, done: false}
console.log(iter2.next()); // {value: 7, done: false}
console.log(iter2.next()); // {value: 9, done: false}
console.log(iter2.next()); // {value: undefined, done: true}
이제 위 함수는 10 까지 홀수만을 반환하는 제너레이터가 되었다.
이번엔 좀더 재밌게, 좀더 많은 제너레이터를 활용하는 함수를 만들어 보자.
값을 무한히 증가시키는 제너레이터를 구현해보자
// 이 제너레이터는 0 부터 시작해서, 또는 넘겨준 값으로 시작해서
// 무한히 값을 증가시켜주며 값을 발생시키는 함수를 만들었다고 가정해보자
function* infinity(i = 0) {
while (true) yield i++;
}
let infinityIter = infinity();
console.log(infinityIter.next()); // {value: 1, done: false}
console.log(infinityIter.next()); // {value: 2, done: false}
console.log(infinityIter.next()); // {value: 3, done: false}
console.log(infinityIter.next()); // {value: 4, done: false}
console.log(infinityIter.next()); // {value: 5, done: false}
console.log(infinityIter.next()); // {value: 6, done: false}
console.log(infinityIter.next()); // {value: 7, done: false}
console.log(infinityIter.next()); // {value: 8, done: false}
// ...
// 이 infinity 제너레이터는 직접 next() 를 할때만 값이 증가하기 때문에,
// for...of 문에 사용하지 않는이상 브라우저가 멈추거나 프로그램이 죽는 일은 없다.
// 이런식으로 무한 수열을 표현할수 있다.
위에서 홀수만을 생성했던 제너레이터를 좀더 재밌게 변형해보자
function* infinity(i = 0) {
while (true) yield i++;
}
function* odds(limit: number) {
for (const idx of infinity(1)) {
if (idx % 2) yield idx;
if (idx === limit) return;
}
}
let oddsIter = odds(10);
console.log(oddsIter.next()); // {value: 1, done: false}
console.log(oddsIter.next()); // {value: 3, done: false}
console.log(oddsIter.next()); // {value: 5, done: false}
console.log(oddsIter.next()); // {value: 7, done: false}
console.log(oddsIter.next()); // {value: 9, done: false}
console.log(oddsIter.next()); // {value: undefined, done: true}
제너레이터에 제너레이터를 실행시켜 무한히 홀수만을 반환하는 제너레이터가 되었다 !
여기에 또다른 제너레이터를 하나 더 추가시켜 보자
이번엔 limit 을 설정하는 제너레이터를 만들어보자
// 이 함수는 이터러블을 받아서, 계속해서 안에 있는 값을 yield 를 하다가
// 받아둔 limit 값을 만나면 더이상 코드가 실행되지 않도록 동작하는 함수다.
function* limit(limit: number, iter) {
for (const idx of iter) {
yield idx;
if (idx === limit) return;
}
}
let limitIter = limit(4, [1, 2, 3, 4, 5, 6])
console.log(limitIter.next()) // {value: 1, done: false}
console.log(limitIter.next()) // {value: 2, done: false}
console.log(limitIter.next()) // {value: 3, done: false}
console.log(limitIter.next()) // {value: 4, done: false}
console.log(limitIter.next()) // {value: undefined, done: true}
이제 이 제너레이터들을 모두 조합해서 아까와 같은 동작을 하게 할수 있다.
function* infinity(i = 0) {
while (true) yield i++;
}
function* limit(limit: number, iter) {
for (const idx of iter) {
yield idx;
if (idx === limit) return;
}
}
function* odds(limitNum: number) {
for (const idx of limit(limitNum, infinity(1))) {
if (idx % 2) yield idx;
}
}
let oddsIter = odds(10);
console.log(oddsIter.next()); // {value: 1, done: false}
console.log(oddsIter.next()); // {value: 3, done: false}
console.log(oddsIter.next()); // {value: 5, done: false}
console.log(oddsIter.next()); // {value: 7, done: false}
console.log(oddsIter.next()); // {value: 9, done: false}
console.log(oddsIter.next()); // {value: undefined, done: true}
for (const idx of odds(40)) console.log(idx); // 1 3 5 7 9 ... 39
제너레이터 코드를 활용하여 이렇게 다양한 로직들을 만들수 있다.
이렇게 문장으로 만들어 진것들을 순회시키거나 사용할수 있도록 값으로 문장을 다룰 수 있다.
이런 코드 작성 방식은 JS 함수형 프로그래밍에서 좋은 기반이 된다.
'Javascript' 카테고리의 다른 글
map 함수를 구현해보자 ( feat.이터러블 프로토콜 ) - JS ES6+ 함수형 프로그래밍 - 11 (0) | 2022.09.11 |
---|---|
for...of, 전개 연산자, 구조 분해, 나머지 연산자 - JS ES6+ 함수형 프로그래밍 - 10 (0) | 2022.09.11 |
제너레이터와 이터레이터 - JS ES6+ 함수형 프로그래밍 - 8 (0) | 2022.09.09 |
전개 연산자 ( Spread Operator ) - JS ES6+ 함수형 프로그래밍 - 7 (2) | 2022.09.09 |
사용자 정의 이터러블, 이터러블 / 이터레이터 프로토콜 정의 - JS ES6+ 함수형 프로그래밍 - 6 (0) | 2022.09.09 |