Card 02/ 08
Design Patterns Example: Iterator in Three Languages
A Python for loop, a Java for-each and a TypeScript for...of are one solution under three syntaxes.
A pattern is called recurring because the same solution appears wherever the same problem does, and the Iterator pattern is the easiest place to see that. Every time you loop over a list, an iterator object does the walking. This example shows the same loop in Python, Java and TypeScript, first as the loop you normally write and then with the iterator made visible.
In each listing the first loop is the everyday form. The lines after it ask the collection for its iterator and call it directly, which is what the loop does for you.
The loop, then the iterator behind it
words = ["adapter", "bridge", "composite"]
for word in words:
print(word)
iterator = iter(words)
print(next(iterator))
print(next(iterator))
print(next(iterator))
try:
next(iterator)
except StopIteration:
print("StopIteration: nothing left")adapter
bridge
composite
adapter
bridge
composite
StopIteration: nothing leftimport java.util.Iterator;
import java.util.List;
public class WdIterate {
public static void main(String[] args) {
List<String> words = List.of("adapter", "bridge", "composite");
for (String word : words) {
System.out.println(word);
}
Iterator<String> iterator = words.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("hasNext: " + iterator.hasNext());
}
}adapter
bridge
composite
adapter
bridge
composite
hasNext: falseconst words: string[] = ["adapter", "bridge", "composite"];
for (const word of words) {
console.log(word);
}
const iterator = words[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());adapter
bridge
composite
{ value: 'adapter', done: false }
{ value: 'bridge', done: false }
{ value: 'composite', done: false }
{ value: undefined, done: true }The three languages spell it differently, and the shape underneath is the same. The collection creates an iterator. The iterator remembers where it is. Each call hands out the next element, and the iterator says when there are none left.
| Role in the pattern | Python | Java | TypeScript |
|---|---|---|---|
| The collection creates an iterator | iter(words) | words.iterator() | words[Symbol.iterator]() |
| The iterator hands out the next element | next(iterator) | iterator.next() | iterator.next().value |
| The iterator reports the end | raises StopIteration | hasNext() returns false | next() returns done: true |
None of the three loops mentions how a list is stored. That is the problem the pattern solves, and it is why the same loop works over a set, a dictionary's keys or a file's lines: each supplies its own iterator, and the loop only ever calls next.
This is what "recurring" means. Three language designers, years apart, met the same problem and reached the same two roles. A pattern catalogue names those roles once, so you can recognise them in a language you have never used.
← → move through sections and cards