以下打印9,然后true,如预期的那样:
fn main() {
let mut a = (1..10);
println!("{}", a.by_ref().count()); // 9
println!("{}", a.all(|x| x < 10)); // true
}
Run Code Online (Sandbox Code Playgroud)
下面的打印true然后0!
fn main() {
let mut a = (1..10);
println!("{}", a.by_ref().all(|x| x < 10)); // true
println!("{}", a.count()); // 0
}
Run Code Online (Sandbox Code Playgroud)
调用.by_ref()之前不应该调用迭代器以.all防止.all使用迭代器吗?
其他答案涵盖了实施方面的情况,但我想解决术语,我认为这是混淆的根源:
调用
.by_ref()之前不应该调用迭代器以.all防止.all使用迭代器吗?
在 Rust 中,consume有一个与所有权相关的狭义定义——“消耗”一个值的函数从调用者那里获得该值的所有权。由于函数可以自由地销毁值或传递它,因此最初拥有它的调用者无法进一步使用该值。
在实现值的情况下Iterator,使用它们的方法,例如count()或sum(),通常也会耗尽它们(用完它们)。其他方法,例如map()or enumerate(),消耗迭代器并返回一个新的迭代器,如果原始迭代器自身耗尽,则它将耗尽原始迭代器。但是也有像take()or 之类的方法scan,它们消耗迭代器而不必耗尽它,即使它们返回的迭代器已完全耗尽。使用这些方法by_ref()可以方便地保持原始迭代器可用于进一步处理:
let mut iter = 1..1000;
let sum_first_50 = iter.by_ref().take(50).sum();
let sum_second_50 = iter.by_ref().take(50).sum();
// ... iter available to produce the remaining 899 numbers ...
Run Code Online (Sandbox Code Playgroud)
如果没有by_ref()在第一行,第二行不会编译,因为第一take()会消耗(但不排)iter。Withby_ref() iter既不会被消耗(因为by_ref()保护它),也不会被耗尽(因为我们将它与 结合take())。结合by_ref()使用既消耗又耗尽迭代器的方法,例如count(),定义明确但无用,因为它只会让您拥有耗尽的迭代器。
如果您想防止迭代器耗尽(或以其他方式变异),您可以改为克隆它:
fn main() {
let a = 1..10;
println!("{}", a.clone().all(|x| x < 10)); // true
println!("{}", a.count()); // 9
}
Run Code Online (Sandbox Code Playgroud)