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

3
在Exercism.io上进行Rust编程练习(https://exercism.io)时,我发现有些解决方案选择通过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()
}

我想知道在这种情况下Rust何时停止迭代范围。它可能会迭代到类型的最大值,或者通过检查后续代码(例如通过检查示例中.unwrap()不会引发panic的位置)来确定何时可以停止迭代吗?
2个回答

6
Rust中的迭代器是惰性评估的,如果您无限次调用它们的next方法,它们才会"走向无穷"。nthtakeIterator方法在内部有限次调用next,因此没有问题。

然而,如果您在非终止循环中迭代Iterator并且Iterator生成某些基本数字类型,则在尝试超过该类型可表示的最大值时最终会遇到溢出。示例程序:

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

运行时恐慌:
thread 'main' panicked at 'attempt to add with overflow', /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/ops/arith.rs:107:1

但是这并不意味着无法无限迭代!一些方法,例如 cycle,允许您创建一个无限重复的序列,它将一直运行直到您手动终止程序:

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

2
请注意,溢出时的恐慌只会在调试模式下发生。在发布模式下,它将无限循环。 - maxy

2
这是由于使用了 Iterator::nth 方法。该方法会在迭代器上调用 next 方法恰好 n 次,然后停止。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接