Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The yield statement is a control flow operator used exclusively within generator functions (sync* or async*) to emit a sequence of values one at a time. It suspends the execution of the function, delivers the evaluated expression to the consuming Iterable or Stream, and retains the function’s local state so execution can resume from that exact point upon the next iteration request.

Syntax

// Emits a single value
yield expression;

// Delegates to another Iterable or Stream
yield* iterableOrStreamExpression;

Mechanics of yield

When the Dart runtime encounters a yield statement, the following sequence occurs:
  1. Evaluation: The expression following the yield keyword is evaluated.
  2. Emission: The resulting value is added to the output sequence (Iterable for synchronous generators, Stream for asynchronous generators).
  3. Suspension: The execution of the generator function is paused immediately after the yield statement. All local variables and execution state are preserved in memory.
  4. Resumption: The function remains suspended until the consumer requests the next value (e.g., via Iterator.moveNext() for an Iterable, or when the StreamSubscription is ready for the next event). Once requested, execution resumes at the statement immediately following the yield.

Synchronous vs. Asynchronous Contexts

The behavior of yield adapts based on the generator’s modifier: Synchronous Generator (sync*) Emits values to an Iterable<T>. The suspension is driven by the synchronous pulling of values via an Iterator.
Iterable<int> generateSynchronous() sync* {
  yield 1; // Pauses until iterator.moveNext() is called
  yield 2;
}
Asynchronous Generator (async*) Emits values to a Stream<T>. The suspension is driven by the asynchronous event loop and the backpressure of the stream’s subscription.
Stream<int> generateAsynchronous() async* {
  yield 1; // Emits to the stream, pauses until the stream is ready
  yield 2;
}

The yield* (Yield-Each) Operator

The yield* statement is a delegation operator. Instead of emitting a single value, it delegates the emission process to another Iterable or Stream. When yield* is invoked, the current generator pauses and forwards all values from the target collection to the consumer. The current generator only resumes execution once the delegated Iterable or Stream is completely exhausted.
Iterable<int> subSequence() sync* {
  yield 2;
  yield 3;
}

Iterable<int> mainSequence() sync* {
  yield 1;
  yield* subSequence(); // Flattens the subSequence into the current Iterable
  yield 4;
}
// Resulting sequence: 1, 2, 3, 4

Technical Constraints

  • yield and yield* result in a compile-time error if used outside of functions marked with sync* or async*.
  • A return statement inside a generator function terminates the sequence, closing the underlying Iterable or Stream. It does not emit a value.
  • In an async* function, yield* must delegate to a Stream, whereas in a sync* function, it must delegate to an Iterable.
Master Dart with Deep Grasping Methodology!Learn More