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.