.NET Iterators in the
.NET Framework (i.e. C#) are called "enumerators" and represented by the IEnumerator interface.IEnumerator provides a MoveNext() method, which advances to the next element and indicates whether the end of the collection has been reached; a Current property, to obtain the value of the element currently being pointed at; and may optionally support a However, support for iterators was added in PHP 5 through the introduction of the internal Traversable interface. The two main interfaces for implementation in PHP scripts that enable objects to be iterated via the foreach loop are Iterator and IteratorAggregate. The latter does not require the implementing class to declare all required methods, instead it implements an
accessor method (getIterator) that returns an instance of Traversable. The
Standard PHP Library provides several classes to work with special iterators. PHP also supports
Generators since 5.5. The simplest implementation is by wrapping an array, this can be useful for
type hinting and
information hiding. namespace Wikipedia\Iterator; final class ArrayIterator extends \Iterator { private array $array; public function __construct(array $array) { $this->array = $array; } public function rewind(): void { echo 'rewinding' , PHP_EOL; reset($this->array); } public function current() { $value = current($this->array); echo "current: {$value}", PHP_EOL; return $value; } public function key() { $key = key($this->array); echo "key: {$key}", PHP_EOL; return $key; } public function next() { $value = next($this->array); echo "next: {$value}", PHP_EOL; return $value; } public function valid(): bool { $valid = $this->current() !== false; echo 'valid: ', ($valid ? 'true' : 'false'), PHP_EOL; return $valid; } } All methods of the example class are used during the execution of a complete foreach loop (foreach ($iterator as $key => $current) {}). The iterator's methods are executed in the following order: • $iterator->rewind() ensures that the internal structure starts from the beginning. • $iterator->valid() returns
true in this example. • $iterator->current() returned value is stored in $value. • $iterator->key() returned value is stored in $key. • $iterator->next() advances to the next element in the internal structure. • $iterator->valid() returns
false and the loop is aborted. The next example illustrates a PHP class that implements the Traversable interface, which could be wrapped in an IteratorIterator class to act upon the data before it is returned to the foreach loop. The usage together with the MYSQLI_USE_RESULT constant allows PHP scripts to iterate result sets with billions of rows with very little memory usage. These features are not exclusive to PHP nor to its
MySQL class implementations (e.g. the PDOStatement class implements the Traversable interface as well). mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); $mysqli = new \mysqli('host.example.com', 'username', 'password', 'database_name'); // The \mysqli_result class that is returned by the method call implements the internal Traversable interface. foreach ($mysqli->query('SELECT `a`, `b`, `c` FROM `table`', MYSQLI_USE_RESULT) as $row) { // Act on the returned row, which is an associative array. }
Python Iterators in
Python are a fundamental part of the language and in many cases go unseen as they are implicitly used in the for (
foreach) statement, in
list comprehensions, and in
generator expressions. All of Python's standard built-in
collection types support iteration, as well as many classes that are part of the standard library. The following example shows typical implicit iteration over a sequence: for value in sequence: print(value) Python dictionaries (a form of
associative array) can also be directly iterated over, when the dictionary keys are returned; or the items() method of a dictionary can be iterated over where it yields corresponding key,value pairs as a tuple: for key in dictionary: value = dictionary[key] print(key, value) for key, value in dictionary.items(): print(key, value) Iterators however can be used and defined explicitly. For any iterable sequence type or class, the built-in function iter() is used to create an iterator object. The iterator object can then be iterated with the next() function, which uses the __next__() method internally, which returns the next element in the container. (The previous statement applies to Python 3.x. In Python 2.x, the next() method is equivalent.) A StopIteration exception will be raised when no more elements are left. The following example shows an equivalent iteration over a sequence using explicit iterators: from typing import Iterator sequence: list[int] = [1, 2, 3, 4] it: Iterator[int] = iter(sequence) while True: try: value = it.next() # in Python 2.x value = next(it) # in Python 3.x except StopIteration: break print(value) Any user-defined class can support standard iteration (either implicit or explicit) by defining an __iter__() method that returns an iterator object. The iterator object then needs to define a __next__() method that returns the next element. Python's
generators implement this iteration
protocol.
Raku Iterators in
Raku are a fundamental part of the language, although usually users do not have to care about iterators. Their usage is hidden behind iteration APIs such as the for statement, map, grep, list indexing with .[$idx], etc. The following example shows typical implicit iteration over a collection of values: my @values = 1, 2, 3; for @values -> $value { say $value } • OUTPUT: • 1 • 2 • 3 Raku hashes can also be directly iterated over; this yields key-value Pair objects. The kv method can be invoked on the hash to iterate over the key and values; the keys method to iterate over the hash's keys; and the values method to iterate over the hash's values. my %word-to-number = 'one' => 1, 'two' => 2, 'three' => 3; for %word-to-number -> $pair { say $pair; } • OUTPUT: • three => 3 • one => 1 • two => 2 for %word-to-number.kv -> $key, $value { say "$key: $value" } • OUTPUT: • three: 3 • one: 1 • two: 2 for %word-to-number.keys -> $key { say "$key => " ~ %word-to-number{$key}; } • OUTPUT: • three => 3 • one => 1 • two => 2 Iterators however can be used and defined explicitly. For any iterable type, there are several methods that control different aspects of the iteration process. For example, the iterator method is supposed to return an Iterator object, and the pull-one method is supposed to produce and return the next value if possible, or return the
sentinel value IterationEnd if no more values could be produced. The following example shows an equivalent iteration over a collection using explicit iterators: my @values = 1, 2, 3; my $it := @values.iterator; # grab iterator for @values loop { my $value := $it.pull-one; # grab iteration's next value last if $value =:= IterationEnd; # stop if we reached iteration's end say $value; } • OUTPUT: • 1 • 2 • 3 All iterable types in Raku compose the Iterable role, Iterator role, or both. The Iterable is quite simple and only requires the iterator to be implemented by the composing class. The Iterator is more complex and provides a series of methods such as pull-one, which allows for a finer operation of iteration in several contexts such as adding or eliminating items, or skipping over them to access other items. Thus, any user-defined class can support standard iteration by composing these roles and implementing the iterator and/or pull-one methods. The DNA class represents a DNA strand and implements the iterator by composing the Iterable role. The DNA strand is split into a group of trinucleotides when iterated over: subset Strand of Str where { .match(/^^ + $$/) and .chars %% 3 }; class DNA does Iterable { has $.chain; method new(Strand:D $chain) { self.bless: :$chain } method iterator(DNA:D:){ $.chain.comb.rotor(3).iterator } }; for DNA.new('GATTACATA') { .say } • OUTPUT: • (G A T) • (T A C) • (A T A) say DNA.new('GATTACATA').map(*.join).join('-'); • OUTPUT: • GAT-TAC-ATA The Repeater class composes both the Iterable and Iterator roles: class Repeater does Iterable does Iterator { has Any $.item is required; has Int $.times is required; has Int $!count = 1; multi method new($item, $times) { self.bless: :$item, :$times; } method iterator { self } method pull-one(--> Mu){ if $!count
Ruby Ruby implements iterators quite differently; all iterations are done by means of passing callback closures to container methods - this way Ruby not only implements basic iteration but also several patterns of iteration like function mapping, filters and reducing. Ruby also supports an alternative syntax for the basic iterating method each, the following three examples are equivalent: (0...42).each do |n| puts n end ...and... for n in 0...42 puts n end or even shorter 42.times do |n| puts n end Ruby can also iterate over fixed lists by using Enumerators and either calling their #next method or doing a for each on them, as above.
Rust Rust makes use of external iterators throughout the standard library, including in its for loop, which implicitly calls the next() method of an iterator until it is consumed. The most basic for loop for example iterates over a Range type: for i in 0..42 { println!("{}", i); } // Prints the numbers 0 to 41 Specifically, the for loop will call a value's into_iter() method, which returns an iterator that in turn yields the elements to the loop. The for loop (or indeed, any method that consumes the iterator), proceeds until the next() method returns a None value (iterations yielding elements return a Some(T) value, where T is the element type). All collections provided by the standard library implement the IntoIterator trait (meaning they define the into_iter() method). Iterators themselves implement the Iterator trait, which requires defining the next() method. Furthermore, any type implementing Iterator is automatically provided an implementation for IntoIterator that returns itself. Iterators support various adapters (map(), filter(), skip(), take(), etc.) as methods provided automatically by the Iterator trait. Users can create custom iterators by creating a type implementing the Iterator trait. Custom collections can implement the IntoIterator trait and return an associated iterator type for their elements, enabling their use directly in for loops. Below, the Fibonacci type implements a custom, unbounded iterator: struct Fibonacci(u64, u64); impl Fibonacci { pub fn new() -> Self { Self(0, 1) } } impl Iterator for Fibonacci { type Item = u64; fn next(&mut self) -> Option { let next = self.0; self.0 = self.1; self.1 = self.0 + next; Some(next) } } fn main() { let fib = Fibonacci::new(); for n in fib.skip(1).step_by(2).take(4) { println!("{n}"); } // Prints 1, 2, 5, and 13 } ==See also==