Iterable and Collections
We have learned that instances of Array, ArrayList and other collection types, as well as Range, can be traversed using a for-in loop expression. Can a user-defined type be traversed in a similar way? Yes.
Range, Array, ArrayList, etc., all use the Iterable interface to support the for-in syntax.
Iterable<T> is a built-in interface of the following form (non-essential code is omitted):
interface Iterable<T> {
func iterator(): Iterator<T>
...
}
The iterator member function, in turn, returns a value of the Iterator<T> type, another built-in interface type of the following form (again, only the relevant code is shown):
interface Iterator<T> <: Iterable<T> {
mut func next(): Option<T>
...
}
You can use the for-in syntax to traverse an instance of any type that implements the Iterable<T> interface for a certain type T (which can also be a type variable).
Assume that there is such a for-in expression:
let list = [1, 2, 3]
for (i in list) {
println(i)
}
It is actually equivalent to the following while loop expression:
let list = [1, 2, 3]
var it = list.iterator()
while (true) {
match (it.next()) {
case Some(i) => println(i)
case None => break
}
}
Another common method for traversing an instance of an Iterable type is to use while-let. For example, another equivalent writing method of the while code above is as follows:
let list = [1, 2, 3]
var it = list.iterator()
while (let Some(i) <- it.next()) {
println(i)
}
The Array, ArrayList, HashSet, and HashMap types all implement Iterable. Therefore, their instances can be used in a for-in or while-let expression. You can have the types that you define implement Iterable to enable such traversal.