Rust 如何知道何时停止在没有上限的范围内迭代?

Sok*_*dez 2 iterator loops range infinite-loop rust

对于exercism.io上的Nth Prime Rust 练习,我发现一些解决方案选择了一个没有上限的范围。filter()

下面是一个例子:

pub fn nth(n: u32) -> u32 {
    let mut primes = Vec::with_capacity((n as usize) + 1);

    (2..)
        .filter(|candidate| {
            if !primes.iter().any(|i| candidate % i == 0) {
                primes.push(*candidate);
                true
            } else {
                false
            }
        })
        .nth(n as usize)
        .unwrap()
}
Run Code Online (Sandbox Code Playgroud)

我想知道 Rust 在这种情况下何时停止迭代范围。它可能会迭代到类型的最大值,还是可以通过检查迭代器后面的代码来确定何时可以停止迭代(例如,通过检查.unwrap()示例中的何时不恐慌)?

kfe*_*v91 6

IteratorRust 中的 s 是惰性求值的,因此如果您next无限次调用它们的方法,它们只会“趋于无穷” 。Iteratornthtake内部调用next有限次数的方法,因此没有问题。

但是,如果您Iterator在非终止循环中迭代并且Iterator产生一些原始数字类型,那么当您尝试迭代器超过该类型可表示的最大值时,您最终会遇到溢出。示例程序:

fn main() {
    for _ in (usize::MAX-1..) {
        println!("counting...");
    }
}
Run Code Online (Sandbox Code Playgroud)

运行时恐慌:

thread 'main' panicked at 'attempt to add with overflow', /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/ops/arith.rs:107:1
Run Code Online (Sandbox Code Playgroud)

但这并不意味着不可能永远迭代!有些方法cycle允许你创建一个无限重复的序列,它真的会永远持续下去,直到你手动终止程序:

fn main() {
    let a = [1, 2, 3];
    
    let mut infinite_123 = a.iter().cycle();
    
    for _ in infinite_123 {
        println!("uh oh, forever loop");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,溢出恐慌仅发生在调试模式下。在发布模式下它将永远循环。 (2认同)