Skip to main content
The for-in loop is a control flow statement that iterates sequentially over the elements of an object implementing the Iterable interface, such as List, Set, or Map.keys. It abstracts the management of the iterator index and termination condition, executing a statement block for each element in the collection.

Syntax

for (var candidate in iterable) {
  // Statement(s) to execute
}

Parameters

  • candidate: A variable declaration (using var, final, or an explicit type) that holds the value of the current element during a specific iteration. This variable is scoped to the loop body.
  • iterable: An expression evaluating to an object that implements Iterable<T>.

Execution Mechanics

When a for-in loop executes, the Dart runtime performs the following operations:
  1. Iterator Instantiation: The runtime calls the iterator getter on the provided iterable object.
  2. Iteration Cycle:
    • The runtime calls moveNext() on the iterator.
    • If moveNext() returns false, the loop terminates.
    • If moveNext() returns true, the current value of the iterator is assigned to the candidate variable.
  3. Block Execution: The code block within the braces executes.
  4. Repeat: Control returns to the start of the Iteration Cycle.

Standard Iteration

In this example, the loop iterates through a List<String>. The variable element is implicitly assigned the value of the current item in the list for each pass.
const data = ['Packet A', 'Packet B', 'Packet C'];

for (final element in data) {
  print(element);
}

Pattern Matching and Destructuring

Dart 3 introduced pattern matching, allowing the for-in loop to destructure elements directly within the loop declaration. This is particularly effective when iterating over lists of records or objects.
const coordinates = [
  (x: 10, y: 20),
  (x: 15, y: 25),
];

// Destructures the record immediately into local variables x and y
for (var (:x, :y) in coordinates) {
  print('Position: $x, $y');
}

Asynchronous Iteration (await for)

For asynchronous sequences of data (Streams), Dart utilizes the await for variation. This construct pauses execution of the enclosing async function until the stream emits a new value or closes.
Stream<int> numberStream() async* {
  yield 1;
  yield 2;
  yield 3;
}

void main() async {
  // Iterates as values become available from the Stream
  await for (final number in numberStream()) {
    print(number);
  }
}
Master Dart with Deep Grasping Methodology!Learn More