How do I use a for loop to iterate over a collection?

← Control Flow · Ref: Q65

EK9's for-in loop iterates over any collection or iterable. The syntax is 'for item in collection'. This is the EK9 equivalent of Java's enhanced for, Python's for-in, and Rust's for-in.

LIST ITERATION

Iterate over each element in a list:

  fruits <- ["apple", "banana", "cherry"]
  for fruit in fruits
    stdout.println(fruit)

The loop variable 'fruit' is implicitly declared with the element type.

DICT ITERATION

Iterate over dictionary entries:

  ages <- {"Alice": 30, "Bob": 25}
  for entry in ages
    stdout.println($entry)

Each entry is a DictEntry with key and value properties. See Q46 for Dict details.

ITERATOR PATTERN

You can also iterate using an explicit iterator:

  items <- ["one", "two", "three"]
  iter <- items.iterator()
  while iter?
    stdout.println(iter.next())

The ? operator checks if the iterator has more items (isSet). See Q66 for while loop details.

FOR-IN VS FOR-RANGE

For-in iterates over a collection's elements. For-range iterates over a numeric range:

  for item in myList        for-in: each element
  for i in 1 ... 10         for-range: each number

Use for-in when you have a collection. Use for-range when you need a counting loop (see Q64).

WORKS WITH ANY ITERABLE

For-in works with any type that provides an iterator. This includes List, Dict, and any user-defined type that implements the iterator pattern.

NO BREAK OR CONTINUE

For-in loops always process every element. There is no break to stop early and no continue to skip elements. If you need to filter or limit items, use a stream pipeline instead:

  cat fruits | filter by isLong > stdout

See Q86 for early exit alternatives and Q87 for skip alternatives.

For-in can also return values as an expression (see Q80). Guard variables can be used in for-in (see Q74).

See Q45 for List type details. See Q46 for Dict type details. See Q64 for for-range loops. See Q89 for stream pipelines as alternatives to for-in loops. See Q120 for sorting streams. See Q125 for head as the only early exit mechanism.

Example

defines module qa.flow.collection.loop

  defines function

    isLong() as pure
      -> text as String
      <- rtn <- false
      expectedCount <- 4
      rtn: length text > expectedCount

  defines program

    ForInDemo()
      stdout <- Stdout()

      // === LIST ITERATION ===

      fruits <- ["apple", "banana", "cherry", "date"]
      stdout.println("Fruits:")
      for fruit in fruits
        stdout.println(`  ${fruit}`)

      // === LIST OF NUMBERS ===

      numbers <- [10, 20, 30, 40, 50]
      total <- 0
      for num in numbers
        total: total + num
      stdout.println(`Sum: ${total}`)

      // === DICT ITERATION ===

      ages <- {"Alice": 30, "Bob": 25, "Charlie": 35}
      stdout.println("Ages:")
      for entry in ages
        stdout.println(`  ${entry}`)

      // === NESTED ITERATION ===

      matrix <- [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
      stdout.println("Matrix:")
      for row in matrix
        for item in row
          stdout.println(`  ${item}`)

      // === STREAM ALTERNATIVE (filter) ===

      stdout.println("Long fruit names (>4 chars):")
      cat fruits | filter by isLong > stdout

Common mistakes

E01070 — EK9 has no break statement. For-in loops always process every element. Use stream pipelines with head to stop early. See ek9 -h E01070 for details.

Incorrect:

for fruit in fruits
        if fruit == "cherry"
          break
        stdout.println(`  ${fruit}`)

Correct:

for fruit in fruits
        stdout.println(`  ${fruit}`)

E01071 — EK9 has no continue statement. Use filter in a stream pipeline to skip unwanted items, or use an if block inside the loop body. See ek9 -h E01071 for details.

Incorrect:

for num in numbers
        if num == 0
          continue
        total: total + num

Correct:

for num in numbers
        total: total + num
Other ways to ask this
  • How do I loop through a list in EK9?
  • How does for-each work in EK9?
  • How do I iterate over a dictionary in EK9?
  • How do collection-based for loops work in EK9?
  • How do I use a for loop to iterate over items?

Coming from another language?

Java: for (String item : list) enhanced for loop, or list.forEach(item -> ...) with lambda. Python: for item in list with direct iteration, enumerate() for index+value. Rust: for item in &list with borrowing semantics, .iter() for references, .into_iter() for ownership. Go: for _, item := range list with blank identifier for index, for k, v := range map for maps. C++: for (auto& item : list) range-based for since C++11. Kotlin: for (item in list) with direct iteration, forEachIndexed for index+value. C#: foreach (var item in list) with IEnumerable. JavaScript: for (const item of list) with for-of, .forEach() method. Swift: for item in list with direct iteration. EK9: for item in list with direct iteration, works with List, Dict, and any iterable type, no break/continue.

Keywords: entry, condition, flow, list, iterator, iterate, loop, dict, branch, in, migrate, dictionary, each, collection, control, for, element