← Iterator lesson
Lab

Iterator / generator

type Pairing = { white: string; black: string };
type Page = { pairings: Pairing[]; next: number | null };

// The schedule service: pairings in start-time order, a page at a time.
class Schedule {
  log: string[] = [];
  pages: Pairing[][];
  constructor(pages: Pairing[][]) {
    this.pages = pages;
  }
  open(): void {
    this.log.push('open');
  }
  fetch(page: number): Page {
    this.log.push(`fetch ${page}`);
    const next = page < this.pages.length ? page + 1 : null;
    return { pairings: this.pages[page - 1], next };
  }
  close(): void {
    this.log.push('close');
  }
}

// The iterator: it keeps the page, its place and the session.
function* pairings(schedule: Schedule): Generator<Pairing> {
  schedule.open();
  try {
    let page: number | null = 1;
    while (page !== null) {
      const fetched = schedule.fetch(page);
      for (const pairing of fetched.pairings) yield pairing;
      page = fetched.next;
    }
  } finally {
    schedule.close();
  }
}

// The floor marshal posts pairings until the board's three slots are full.
const schedule = new Schedule([
  [{ white: 'Ayla', black: 'Boris' }, { white: 'Camila', black: 'Dinesh' }],
  [{ white: 'Edda', black: 'Finn' }, { white: 'Gita', black: 'Hugo' }],
  [{ white: 'Ines', black: 'Jamal' }],
]);
const board: string[] = [];
for (const pairing of pairings(schedule)) {
  board.push(`${pairing.white} vs ${pairing.black}`);
  if (board.length === 3) break;
}
const log = schedule.log.join(', ');
console.log(board.join(' | '));
console.log(log);