Сначала давайте посмотрим на реализации:
Range
реализует Iterator
. for
выполняет цикл десахара до вызова std::iter::IntoIterator::into_iter
, что реализовано для всего, что уже является итератором (поскольку вы, очевидно, можете создать итератор из итератора - просто верните итератор). Кроме того, Iterator
реализован для (и только) &mut
ссылок на существующие итераторы .
Отсюда мы можем вывести ошибку:
- Вы можете выполнять итерацию над всем, что реализует
IntoIterator
. - Вы можете превратить любое
Iterator
в * С 1026 * по IntoIterator
. Что ничего не делает. Iterator
реализовано только для уникальных (&mut
) ссылок на другие Iterator
s.
Следовательно, вы не можете использовать итератор более &Range
s, а вместо этого только &mut Range
s или Range
s.
Вместо этого нужно сделать либо Clone
Range
:
let my_range = 10..40;
for i in my_range.clone() {
println!("{:?}", i);
}
Взять изменяемую ссылку на диапазон (тем самым опустошив и его) :
let mut my_range = 10..40;
for i in &mut my_range {
println!("{:?}", i);
}
assert_eq!(my_range.next(), None);
Или проделайте более идиоматическое c действие, просто каждый раз увеличивая диапазон:
for i in 10..40 {
println!("{:?}", i);
}
Это очень дешево.
Кроме того, эти правила о реализациях трейта Iterator
для &mut
, а не &
ссылок, применяются ко всем итераторам. Это позволяет нам делать что-то вроде этого:
let mut my_iter = 0..100;
// Only take first 50 elements.
for x in (&mut my_iter).take(50) {
println!("{:?} < 50", x);
}
for x in my_iter {
println!("{:?} >= 50", x);
}
Обратите внимание, что take
принимает self
, однако self
равно &mut Range
, поэтому мы не используем вверх оригинал Range
.