Awesome
Iterator Sequencing
A TC39 proposal to create iterators by sequencing existing iterators.
Stage: 2
motivation
Often you have 2 or more iterators, the values of which you would like to
consume in sequence, as if they were a single iterator. Iterator libraries (and
standard libraries of other languages) often have a function called concat
or
chain
to do this. In JavaScript today, one can accomplish this with generators:
let lows = Iterator.from([0, 1, 2, 3]);
let highs = Iterator.from([6, 7, 8, 9]);
let lowsAndHighs = function* () {
yield* lows;
yield* highs;
}();
Array.from(lowsAndHighs); // [0, 1, 2, 3, 6, 7, 8, 9]
It is also useful to be able to sequence immediate values among the iterators,
as one would do with yield
using the generator approach.
let digits = function* () {
yield* lows;
yield 4;
yield 5;
yield* highs;
}();
Array.from(digits); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
We should explore how to make this more ergonomic and functional.
chosen solution
See the June 2024 presentation to committee.
let digits = Iterator.concat(lows, [4, 5], highs);
function* p() {
for (let n = 1;; ++n) {
yield Array(n).fill(n);
}
}
let repeatedNats = p().flatMap(x => x);
considered design space
- make
Iterator.from
variadicIterator.from(as, bs, cs)
- add
Iterator.prototype.concat
/append
/chain
as.concat(bs).concat(cs)
- have to already have an iterator for this
concat
may make some people think that it accepts non-iterators, as analogue toArray.prototype
- add
Iterator.of
for lifting immediate values to an iteratorIterator.of(as, bs, cs).flatMap(x => x)
- add
Iterator.prototype.flat
to eliminate the identity function - is it actually that much better than
[as, bs, cs].values()
?
- add
Iterator.concat(xs)
- short for
Iterator.from(x).flat()
- short for
- do we close iterators that haven't been consumed when the result iterator is closed?
prior art
other languages
language | data type | exactly 2 | arbitrary |
---|---|---|---|
Clojure | lazy seq | concat | |
Elm | List | append /++ | concat |
Haskell | Semigroup | <> | mconcat |
OCaml | Seq | append | concat |
Python | iterator | chain | |
Ruby | Enumerable | chain | |
Rust | Iterator | chain | flatten |
Scala | Iterator | concat /++ | |
Swift | LazySequence | joined |
JS libraries
library | exactly 2 | arbitrary |
---|---|---|
@softwareventures/iterator | prependOnce /appendOnce | concatOnce |
extra-iterable | concat | |
immutable.js | Seq::concat | |
iterablefu | concatenate | |
itertools-ts | chain | |
lodash | flatten | |
ramda | concat | unnest |
sequency | plus | |
wu | chain |