2015-09-05 30 views
4

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

什么是这种行为的原因是什么?

回答

7

类型推断导致您范围内的两个数字都是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 { 
       ^~ 

另外请注意,你不应该接受&Vec<T>作为参数。始终使用&[T],因为它更灵活,并且不会丢失任何东西。

+2

这是令人惊讶的行为。我希望'rustc'至少会发出一个警告,即负值被“包裹”。 –

+0

@MatthieuM。哦,谢谢你提醒我!它实际上*是*固定的,看我的更新。^_^ – Shepmaster

+0

啊!谈好时机! –