1 of 14

Helping Iterators

Michael Ficarra • June 2024�(iterator helpers champion)

2 of 14

easiest quiz of your life:

what do all of these JavaScript features have in common?

for (let a of iterable);

[ ...iterable ]

let [a, b] = iterable;

Object.fromEntries(iterable)

for-of loop

Array spread

positional destructuring

iterable-taking built-ins

3 of 14

ITERATOR PROTOCOL!

4 of 14

what makes iterators so great?

they're lazy sequences!

  • reduced memory usage
  • defer computation until it's needed
  • for partial consumers, eliminate unnecessary work
  • construct infinite sequences

5 of 14

iteration protocol (approximation)

interface Iterable<T> {

[Symbol.iterator](): Iterator<T>;

}

interface Iterator<T> {

next(): IteratorResult<T>;

return?(): IteratorResult<T>;

}

type IteratorResult<T>

= { done: false, value: T }

| { done: true, value?: undefined };

6 of 14

easy ways to create your own iterators

1) iterate a finite collection type:

  • Array / Set / Map
  • prototype methods:
    • [Symbol.iterator]()
    • keys()
    • values()
    • entries()

Object.fromEntries(map.entries())

2) write a generator:

function* nats() {

for (let i = 0; ; ++i) {

yield i;

}

}

let [zero, one, two] = nats();

7 of 14

Iterator.prototype

8 of 14

Stage 3: iterator helpers MVP

(basically just Array analogues)

transform iterators

  • map
  • filter
  • flatMap
  • take / drop (slice analogue)

consume iterators

  • reduce
  • forEach
  • some
  • every
  • find

  • toArray

Iterator.from: ensure an iterator inherits from Iterator.prototype

9 of 14

iterator follow-on proposals

10 of 14

active iterator follow-on proposals

Stage 2 proposal: joint iteration (going for Stage 2.7 this week!)

Iterator.zipToArrays(iterableOfIterables [ , options ])

Iterator.zipToObjects(namedIterables [ , options ])

Stage 1 proposal: iterator sequencing (going for Stage 2 this week!)

Iterator.concat(...iterators)

Stage 1 proposal: iterator chunking

iterator.chunks(chunkSize)

iterator.windows(windowSize, stepSize)

Stage 1 proposal: iterator unique

iterator.distinct( [ exemplarMapper ] )

CAUTION: names and shapes of APIs in in-progress proposals are subject to change

11 of 14

planned iterator follow-on proposals

  • cleanup
  • takeWhile & dropWhile
    • take/drop based on a function of the yielded elements, not a fixed number
  • scan
    • like reduce, but yields every intermediate result of reducer callback
  • tap
    • iterator.map(a => { effect(a); return a; })
  • into / to
    • inline a generator-based transform into a helper chain
    • build a data structure from this iterator

12 of 14

the future of iterators is looking bright!

13 of 14

postlude: async iterator helpers are WIP

urls

.toAsync()

.map(u => fetch(u))

.buffered(2)

.toArray()

14 of 14