为什么从负数开始的范围不会迭代?

Hol*_*ger 4 iterator for-loop rust

我刚开始学习Rust.在我使用这种语言的第一步中,我发现了一种奇怪的行为,当在内部main或另一个函数中执行迭代时,如下例所示:

fn myfunc(x: &Vec<f64>) {
    let n = x.len();
    println!("    n: {:?}", n);
    for i in -1 .. n {
        println!("    i: {}", i);
    }
}

fn main() {
    for j in -1 .. 6 {
        println!("j: {}", j);
    }

    let field = vec![1.; 6];
    myfunc(&field);
}
Run Code Online (Sandbox Code Playgroud)

而在循环main显示正常,没有打印的内部循环myfunc,我得到以下的输出:

j: -1
j: 0
j: 1
j: 2
j: 3
j: 4
j: 5
    n: 6
Run Code Online (Sandbox Code Playgroud)

这种行为的原因是什么?

She*_*ter 7

类型推断导致范围内的两个数字usize都不能代表负数.因此,范围是从usize::MAXn,其中,不具有任何部件.

为了找到这个,我用一个技巧来打印出事物的类型:

let () = -1 .. x.len();
Run Code Online (Sandbox Code Playgroud)

哪个有这个错误:

error: mismatched types:
 expected `core::ops::Range<usize>`,
    found `()`
(expected struct `core::ops::Range`,
    found ()) [E0308]
let () = -1 .. x.len();
    ^~
Run Code Online (Sandbox Code Playgroud)

潜入细节,slice::len返回一个usize.你-1是一个无类型的整数值,它将符合它所需要的任何上下文(如果它没有任何符合它的东西,它将回归到a i32).

在这种情况下,就像你实际打字一样(-1 as usize)..x.len().

好消息是你可能不想开始-1.切片为零索引:

fn myfunc(x: &[f64]) {
    let n = x.len();
    println!("    n: {:?}", n);
    for i in 0..n {
        println!("    i: {}", i);
    }
}
Run Code Online (Sandbox Code Playgroud)

额外的好消息是,这种烦恼在最新版本的Rust中得到了修复.它会引发警告,然后最终出错:

warning: unary negation of unsigned integers will be feature gated in the future
     for i in -1 .. n {
              ^~
Run Code Online (Sandbox Code Playgroud)

另请注意,您绝不应接受a &Vec<T>作为参数.总是使用a,&[T]因为它更灵活,你什么都不会失去.

  • 这是令人惊讶的行为.我希望`rustc`至少会发出警告,表示负值被"包裹"了. (2认同)