Notice
Recent Posts
Recent Comments
Link
«   2026/01   »
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
Archives
Today
Total
관리 메뉴

codingfarm

1. 반복자 패턴 본문

설계/멀티패러다임

1. 반복자 패턴

scarecrow1992 2026. 1. 4. 12:45

0. 소개

반복자 패턴의 구현을 통해 객체지향언어가 함수형 패러다임을 구용하는 방식에 대해 알아보겠다.

1. 반복자 (Iterator)

반복자는 다수의 데이터를 순차적으로 꺼내어 처리할 수 있게 해주는 객체를 나타낸다.

이를통해 사용자는, 특정 자료(트리, 집합, 맵 등)의 내부구조를 몰라도 데이터를 순회할 수 있다.

1.1 반복자의 개념

반복자는 필수적으로 다음 2가지 개념을 가진다.

  1. 다음요소 가져오기 (next)
  2. 남은 요소가 더 있는지 확인하기 (done)

1.2 반복자의 특징

  1. 메모리 효율적
    • 모든 데이터를 한번에 메모리에 올리지 않고 순회 가능
  2. 자료구조와 순회방식 분리
    • 어떠한 자료구조에 대해서도 같은 순회 방법을 제공
  3. 일관된 문법
    • for, foreach 같은 반복문 사용이 가능해짐
  4. 지연순회 제공
    • 순회방식을 객체로 캡슐화

Iterator 인터페이스

반복자의 구조를 간략히 정의하면 아래와 같다.

// 반복자가 아직 완료되지 않음
interface IteratorYieldResult<T> {
  done: false;
  value: T;
}

// 반복자가 완료됨
interface IteratorReturnResult {
  done: true;
  value: undefined;
}

// next() 메서드를 지닌 객체, 앞선 2 종류의 객체 중 하나를 반환한다.
interface Iterator<T> {
  next(): IteratorYieldResult<T> | IteratorReturnResult;
}

export { IteratorYieldResult, IteratorReturnResult, Iterator };

2. ArrayLike로부터 Iterator 생성하기

import {
  Iterator,
  IteratorReturnResult,
  IteratorYieldResult,
} from "./interfaces/iterator";

class ArrayLikeIterator<T> implements Iterator<T> {
  private index = 0;
  constructor(private arrayLike: ArrayLike<T>) {}

  next(): IteratorYieldResult<T> | IteratorReturnResult {
    if (this.index < this.arrayLike.length) {
      return {
        value: this.arrayLike[this.index++],
        done: false,
      };
    } else {
      return { value: undefined, done: true };
    }
  }
}

const arrayLike: ArrayLike<number> = {
  0: 10,
  1: 20,
  2: 30,
  length: 3,
};

const iterator: Iterator<number> = new ArrayLikeIterator<number>(arrayLike);

console.log(iterator.next()); // { value: 10, done: false }
console.log(iterator.next()); // { value: 20, done: false }
console.log(iterator.next()); // { value: 30, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

ArrayLike컬렉션 타입을 지원하는Iterator`를 구현한 코드이다.

3. ArrayLike 역순으로 순회하기

ArrayLike를 역순으로 순회하는 iterator를 만들어보자.

import {
  Iterator,
  IteratorYieldResult,
  IteratorReturnResult,
} from "./interfaces/iterator";

function reverse<T>(arrayLike: ArrayLike<T>): Iterator<T> {
  let idx = arrayLike.length;
  return {
    next(): IteratorYieldResult<T> | IteratorReturnResult {
      if (idx === 0) {
        return { value: undefined, done: true };
      } else {
        return { value: arrayLike[--idx], done: false };
      }
    },
  };
}

const array = ["A", "B", "C"];
const reversed = reverse(array);

console.log(reversed.next().value); // C;
console.log(reversed.next().value); // B;
console.log(reversed.next().value); // A;

3. 지연평가되는 map 함수

map<A,B> map 함수는 AB로 변환하는 함수이다.

이를위해, 아래의 기능이 제공된다.

  1. (일급 함수) Iterator<A>와 A를 B로 변환하는 transform 함수를 받은 후,
  2. (고차 함수) 지연된 Iterator<B>를 반환한다.

여기서 일급함수와 고차함수란 아래와 같다.

  • `일급 함수(First-class Function) : 값처럼 다루어지는 함수, 다른 함수의 인자로 전달되거나 반환된다. 즉 전달되는 함수

  • `고차 함수(Higher-order function) : 함수를 인자로 받거나 반환하는 함수, 즉 전달하는 함수

// transform : 일급함수
// map : 고차함수
function map<A, B>(
  transform: (value: A) => B,
  iterator: Iterator<A>
): Iterator<B> {
  return {
    next(): IteratorYieldResult<B> | IteratorReturnResult {
      const { value, done } = iterator.next();
      return done
        ? { value: undefined, done: true }
        : { value: transform(value), done: false };
    },
  };
}

const array = ["A", "B", "C", "D", "E", "F"];
// reverse()로 배열을 역순회 하는 이터레이터를 만들고
// 각 요소에 toLowerCase를 적용한다.
const iterator = map<string, string>(
  (str) => str.toLowerCase(),
  reverse(array)
);
console.log(iterator.next().value); // f
console.log(iterator.next().value); // e

'설계 > 멀티패러다임' 카테고리의 다른 글

3. 자바스크립트의 이터레이션 프로토콜  (0) 2026.01.04
2. 제너레이터  (0) 2026.01.04
Comments