rust - 通过借用它遍历大小合适的Range <T>

标签 rust range iteration immutability borrow

遍历Range<T>似乎会消耗范围实例,因为into_iter函数获取范围的所有权。通过查看documentation of range,很明显Borrow特性仅适用于动态范围对象。如果不进行克隆,是否有可能在范围内进行迭代,同时又将范围的不可变引用传递给其他函数?

let numbers = 500..4000;

// ERROR [(E0277)]: the trait `std::iter::Iterator` is not implemented for `&std::ops::Range<i32>`
for n in &numbers {
    println!("{}", n);

    do_something_else(&numbers);
    reuse_range(&numbers);
}

// Surprisingly, there are no errors when it comes to argument type of functions.
fn do_something_else(range: &Range<i32>) { }
fn reuse_range(range: &Range<i32>) { }

如上所示,函数可以借用Range<T: Sized>,但编译器本身不允许借用范围。

到目前为止,我已经尝试使用Box智能指针,但是行为是相同的。
简单来说,就可以使用by_ref(),但是由于我们已经可以对同一个对象进行可变的借用,因此这也限制了我们借用不可变的借用。

最佳答案

首先,让我们看一下实现:

Range implements Iterator for将desugar循环到对 std::iter::IntoIterator::into_iter 的调用implemented for everything which is already an iterator(因为显然可以从迭代器创建迭代器-只需返回迭代器即可)。另外, Iterator is implemented for (and only for) &mut references to existing iterators

由此我们可以推断出错误:

  • 您可以迭代实现IntoIterator的任何对象。
  • 您可以通过Iterator将任何Iterator转换为IntoIterator。什么都不做。
  • Iterator仅对其他&mut的唯一(Iterator)引用实现。

  • 因此,您不能在&Range上进行迭代,而只能在&mut RangeRange上进行迭代。

    相反,应该对 Clone the 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);
    

    或者执行每次仅构建范围的更惯用的操作:
    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 takes self ,但是self&mut Range,因此我们不会用尽原始的Range

    关于rust - 通过借用它遍历大小合适的Range <T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62480347/

    相关文章:

    asynchronous - Rust异步不对套接字并行执行

    memory-management - Rust 会释放被覆盖变量的内存吗?

    rust - 使用 kwargs 从 Python Rust 函数调用失败

    Ruby 'Range.last' 没有给出最后一个值。为什么?

    java - Java中字符串匹配方法获取以指定字母开头的单词

    objective-c - 使用对象和键遍历NSArray的最快方法

    rust - 返回数组大小的关联常量

    sql-server - 需要有关 SQL 查询的帮助,从周期表中选择日期范围

    python - 将切片变为范围

    sql - vb.net 循环遍历查询结果