Rust 为什么by_ref不阻止.all使用迭代器?

Rust 为什么by_ref不阻止.all使用迭代器?,rust,Rust,以下打印9,然后按预期为真: fn干线{ 设mut a=1..10; println!{},a.by_ref.count;//9 println!{},a.all | x | x

以下打印9,然后按预期为真:

fn干线{ 设mut a=1..10; println!{},a.by_ref.count;//9 println!{},a.all | x | x<10;//true } 以下为真,则为0

fn干线{ 设mut a=1..10; println!{},a.by|ref.all | x | x<10;//正确 println!{},a.count;//0 } 不应该在调用之前调用迭代器上的.by_ref。all阻止.all使用迭代器?

调用迭代器上的all或count将调用下一次多次。 即使迭代器没有从中移动,其内部状态也会因重复调用next而发生变化

当all以true结尾时,序列的结尾已经到达,因此count仍然可以调用,但产生0

在第一种情况下,count到达序列的末尾,但表示为空序列返回true。

在迭代器上调用all或count将调用接下来的多次。 即使迭代器没有从中移动,其内部状态也会因重复调用next而发生变化

当all以true结尾时,序列的结尾已经到达,因此count仍然可以调用,但产生0


在第一种情况下,count到达序列的末尾,但表示为空序列返回true。

每个迭代器适配器,例如.take、.filter,当然还有.,都只能通过.next函数访问迭代器的元素

.by_ref所做的唯一一件事是,它允许您在使用迭代器适配器之后继续使用迭代器。任何已消耗的元素仍将被消耗。如果您不想这样做,那么应该克隆迭代器

Iterator::by_ref的文档对此进行了解释:

设a=[1,2,3]; 设iter=a.iter; 设和:i32=iter.take5.fold0,| acc,i | acc+i; 断言!总和,6; //如果我们再次尝试使用iter,它将不会起作用。下一行 //给出错误:使用移动值:`iter` //断言!iter。其次,无; //让我们再试一次 设a=[1,2,3]; 设mut-iter=a.iter; //相反,我们添加了一个.by\u ref 设和:i32=iter.by_ref.take2.fold0,| acc,i | acc+i; 断言!总和,3; //现在这很好: 断言!下一步,一些&3; 断言!iter。其次,无;
每个迭代器适配器,例如.take、.filter,当然还有.,都只能通过.next函数访问迭代器的元素

.by_ref所做的唯一一件事是,它允许您在使用迭代器适配器之后继续使用迭代器。任何已消耗的元素仍将被消耗。如果您不想这样做,那么应该克隆迭代器

Iterator::by_ref的文档对此进行了解释:

设a=[1,2,3]; 设iter=a.iter; 设和:i32=iter.take5.fold0,| acc,i | acc+i; 断言!总和,6; //如果我们再次尝试使用iter,它将不会起作用。下一行 //给出错误:使用移动值:`iter` //断言!iter。其次,无; //让我们再试一次 设a=[1,2,3]; 设mut-iter=a.iter; //相反,我们添加了一个.by\u ref 设和:i32=iter.by_ref.take2.fold0,| acc,i | acc+i; 断言!总和,3; //现在这很好: 断言!下一步,一些&3; 断言!iter。其次,无;
其他答案涵盖了实现方面的进展,但我想谈谈术语,我认为这是困惑的根源:

在调用.all之前不应该调用迭代器上的.by_ref阻止.all使用迭代器吗

在Rust中,consume有一个与所有权相关的狭义定义——使用值的函数从调用方获得值的所有权。由于函数可以随意销毁或传递该值,因此最初拥有该值的调用方无法进一步使用该值

对于实现迭代器的值,使用迭代器的方法(如count或sum)通常也会耗尽迭代器。其他方法,如map或enumerate,使用迭代器并返回一个新的迭代器,如果原始迭代器本身已耗尽,则该迭代器将耗尽原始迭代器。但是也有像or这样的方法,它们使用迭代器而不必耗尽迭代器,即使它们返回的迭代器已完全耗尽。使用_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 ...
如果第一行中没有by_ref,第二行就无法编译,因为第一行将消耗但不会耗尽iter。使用by_ref iter既不会因为by_ref保护而消耗,也不会因为我们将其与take结合而耗尽。将_ref与消耗和耗尽迭代器的方法(如count)相结合是定义良好但无用的,因为它只会让您拥有一个耗尽的迭代器

如果要防止迭代器耗尽或发生变异,可以克隆它:

fn main() {
    let a = 1..10;
    println!("{}", a.clone().all(|x| x < 10)); // true
    println!("{}", a.count()); // 9
}

其他的答案包括发生了什么 从实现的角度来看,我不同意,但我想谈谈术语,我认为这是困惑的根源:

在调用.all之前不应该调用迭代器上的.by_ref阻止.all使用迭代器吗

在Rust中,consume有一个与所有权相关的狭义定义——使用值的函数从调用方获得值的所有权。由于函数可以随意销毁或传递该值,因此最初拥有该值的调用方无法进一步使用该值

对于实现迭代器的值,使用迭代器的方法(如count或sum)通常也会耗尽迭代器。其他方法,如map或enumerate,使用迭代器并返回一个新的迭代器,如果原始迭代器本身已耗尽,则该迭代器将耗尽原始迭代器。但是也有像or这样的方法,它们使用迭代器而不必耗尽迭代器,即使它们返回的迭代器已完全耗尽。使用_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 ...
如果第一行中没有by_ref,第二行就无法编译,因为第一行将消耗但不会耗尽iter。使用by_ref iter既不会因为by_ref保护而消耗,也不会因为我们将其与take结合而耗尽。将_ref与消耗和耗尽迭代器的方法(如count)相结合是定义良好但无用的,因为它只会让您拥有一个耗尽的迭代器

如果要防止迭代器耗尽或发生变异,可以克隆它:

fn main() {
    let a = 1..10;
    println!("{}", a.clone().all(|x| x < 10)); // true
    println!("{}", a.count()); // 9
}

啊,这很有帮助,所以在第一个例子中,all甚至没有在元素中循环,因为它已经耗尽了,但它仍然返回true。非常有帮助,谢谢。啊,这很有帮助,所以在第一个例子中,all甚至没有循环通过元素,因为它已经用尽了,但它仍然返回true。非常有帮助,谢谢。