Iteration and indexing
Iteration and indexing
The Iter protocol
[public] trait Iter<T> {
fn next() => T?;
fn check() => bool;
}for x in value lowers to: call value.iter(), then call next() on the result
repeatedly, binding the loop variable to each value, stopping at the first
None.
Two consequences:
- There is no
Iterabletrait. Being iterable means having aniter()method that returns something with anext()yieldingT?. The diagnostic says so directly: the type does not implementiter, which is required forforloops. check()is never called by aforloop. It exists for driving an iterator by hand.
In the standard library only Array (and List, by inheritance) has iter().
Map, IndexMap, string, and JsonArray do not.
for name in names { } // works, Array
for key in map.key_list() { } // the way to walk a Map
for (key, value) in map.entries() { } // or with both halvesDestructuring
for (a, b) in ... and let (a, b) = pair bind against a Pair, calling
get_first() and get_second(). Exactly two names are supported, and the value
has to be a Pair: anything else reports that it cannot be destructured.
This is how Map.for_each is written internally:
[public] fn for_each(action: closure(KT, VT) => void) {
for (key, value) in this.entries() {
action(key, value)
}
}Index and IndexRef
[public] trait Index<I, R> { fn index(index: I) => R; }
[public] trait IndexRef<I, R> { fn index_ref(index: I) => &R; }The compiler picks by context: reading a[i] calls index, while assigning
a[i] = v needs a slot and calls index_ref.
| Type | a[i] |
a[i] = v |
|---|---|---|
Array<T>, List<T> |
yes | yes |
string |
yes, yields char |
no |
Neither is bounds checked.