Esta página ainda não foi traduzida, por isso é exibida em inglês. Ajude a traduzir

expand

Maps each element to an iterable, then flattens the results one level — the same contract as Iterable.expand.

Iterable<B> expand<A, B>(Iterable<B> Function(A a) f, Iterable<A> iterable) FxAsyncIterable<B> expandAsync<A, B>(FutureOr<Iterable<B>> Function(A a) f, FxAsyncIterable<A> iterable) Fx<R> Fx.expand<R>(Iterable<R> Function(T a) f) // chain FxAsync<R> FxAsync.expand<R>(FutureOr<Iterable<R>> Function(T a) f) Iterable<B> flatMap<A, B>(...) // FxTS alias

Lecture

expand is map followed by one level of flattening: each element is turned into a collection of results, and those collections are spliced together into a single flat lazy sequence. It's the tool for "one input, many outputs" — splitting a sentence into words, expanding a user into their orders, turning a range into pairs. expand is the Dart-idiomatic name (it matches Iterable.expand); fxdart also accepts the FxTS spelling flatMap — they're the same operator.

FxTS deviation: in FxTS, the callback can return any mix of plain values and iterables and the operator figures out what to flatten via DeepFlat type magic. Dart has no equivalent of that conditional type, so the Dart port requires f to always return an Iterable<B> — exactly like Iterable.expand. Return a single-element list ([x]) to emit exactly one value per input, or an empty list to emit none.

On the async side, expandAsync's internal state machine has to track "which sub-iterable am I currently draining" between pulls, so it consumes its upstream serially — wrapping it in .concurrent(n) only speeds up pulling already-available items, not an await that happens inside the callback itself. If you need concurrent async work per element, do that work in a .map(...).concurrent(n) stage first, then .expand((list) => list) to flatten the already-resolved lists — see Demo 2.

Demo 1 · Basics

The callback must return an Iterable — here, a 2-element list and a call to String.split:

Demo 2 · Async, the right way to get concurrency

Put the slow await in a .map(...).concurrent(n) stage; let expand flatten the results synchronously:

Try it yourself

Exercise: use expand to split each sentence into words, producing one flat list of words.

Related: map — transform without flattening · flat — flatten an already-nested iterable · mapEffect — map for side effects · concurrent — parallel evaluation