SkillByAIOpen interactive version →

Lesson 21 / 25

Iterator and Visitor in Brief

Walking collections and adding operations to structures.

Traversal without exposing internals

Iterator provides a way to access elements of a collection one by one without exposing its internal structure. It is now built into most languages: JavaScript's iteration protocol ([Symbol.iterator], for...of) and generator functions, Python's __iter__ and generators, and Java's Iterable. Generators also make lazy sequences easy, such as paging through an API. Visitor lets you add new operations to a fixed set of node types without changing those types: each node "accepts" a visitor, which has one method per node type. Compilers and linters use it to walk syntax trees (pretty-printing, type checking, evaluation). In TypeScript, a discriminated union with an exhaustive switch often replaces Visitor with less ceremony. Visitor is a poor fit when node types change often, since every visitor must be updated.

A paginated API as an iterator

An async generator hides the paging details.

async function* allInvoices(client: BillingClient): AsyncGenerator<Invoice> {
  let cursor: string | undefined;
  do {
    const page = await client.listInvoices({ limit: 100, cursor });
    yield* page.items;
    cursor = page.nextCursor;
  } while (cursor);
}

// Callers just loop; pages are fetched lazily as needed
for await (const invoice of allInvoices(client)) {
  if (invoice.status === 'overdue') await sendReminder(invoice);
}

// Visitor-like operation via a discriminated union and exhaustive switch
type Expr =
  | { kind: 'num'; value: number }
  | { kind: 'add'; left: Expr; right: Expr }
  | { kind: 'mul'; left: Expr; right: Expr };

function evaluate(e: Expr): number {
  switch (e.kind) {
    case 'num': return e.value;
    case 'add': return evaluate(e.left) + evaluate(e.right);
    case 'mul': return evaluate(e.left) * evaluate(e.right);
  }
}

A museum audio guide

An iterator is the guide that takes you from exhibit to exhibit without you knowing the building layout. A visitor is a specialist (a restorer, an insurer) touring the same exhibits and doing their own kind of work at each.

Quick check: When is Visitor a poor fit?

  • When you need to add new operations to stable node types
  • When new node types are added frequently, because every visitor must change
  • When walking a syntax tree
  • When building a linter
Answer

When new node types are added frequently, because every visitor must change — Visitor favours stable types and changing operations.