export interface List extends Iterable { item: T | null; next: List | null; toArray(): Array; } export function atEnd(xs: List): boolean { return xs.item === null; } export class ArrayList implements List { readonly items: Array; readonly index: number = 0; constructor(items: Array, index = 0) { this.items = items; this.index = index; } get item(): T | null { return this.items[this.index] ?? null; } get next(): List | null { if (this.index >= this.items.length) return null; return new ArrayList(this.items, this.index + 1); } toArray(): Array { return this.items.slice(this.index); } [Symbol.iterator](): Iterator { let i: List = this; return { next(): IteratorResult { const value = i.item; if (!atEnd(i)) i = i.next; return { done: atEnd(i), value }; } }; } }