【问题标题】:Why does a range that starts at a negative number not iterate?为什么从负数开始的范围不会迭代?
【发布时间】:2015-12-01 14:16:38
【问题描述】:

我刚刚开始学习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);
}

虽然main 中的循环正确显示,但myfunc 中的循环没有打印任何内容,我得到以下输出:

j: -1
j: 0
j: 1
j: 2
j: 3
j: 4
j: 5
    n: 6

这种行为的原因是什么?

【问题讨论】:

    标签: for-loop iterator rust


    【解决方案1】:

    类型推断导致您范围内的两个数字都是usize,不能代表负数。因此,范围是从usize::MAXn,它永远不会有任何成员。

    为了弄清楚这一点,我使用了一个技巧来打印出事物的类型:

    let () = -1 .. x.len();
    

    哪个有这个错误:

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

    深入了解细节,slice::len 返回usize。你的-1 是一个无类型的整数值,它将符合它需要的任何上下文(如果没有什么可以符合的,它将回退到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);
        }
    }
    

    额外的好消息是这个烦恼是fixed in the newest versions of Rust。它将导致警告,然后最终出现错误:

    warning: unary negation of unsigned integers will be feature gated in the future
         for i in -1 .. n {
                  ^~
    

    还请注意,您永远不应接受&amp;Vec&lt;T&gt; 作为参数。始终使用&amp;[T],因为它更灵活,而且不会丢失任何东西。

    【讨论】:

    • 这是令人惊讶的行为。我希望rustc 至少会发出一个警告,指出负值被“包裹”了。
    • @MatthieuM。哦,谢谢你提醒我!它实际上固定的,请参阅我的更新。 ^_^
    猜你喜欢
    • 2020-12-20
    • 1970-01-01
    • 2015-04-30
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多