为什么以负数开头的范围不会迭代?

霍尔格

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

这种行为的原因是什么?

Shepmaster

类型推断导致您范围内的两个数字均为,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);
    }
}

额外的好消息是,这种烦恼已在最新版本的Rust中得到了解决它将导致警告,最终导致错误:

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

还要注意,您永远不要接受a&Vec<T>作为参数。始终使用a,&[T]因为它更灵活,而且您一无所获。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么i的值在经过几次迭代后变为负数

为什么范围对象“不是迭代器”?

为什么借用的范围不是迭代器,而是范围?

为什么我得到 Estimate Std。当我使用的数据永远不会是负数时为负数?

为什么使用范围数组未正确迭代值?

为什么当浮点数超出范围时,浮点数不是从负数开始?

TypeScript:为什么 Map 键迭代不会发生?

为什么标准容器迭代器不会重载`-> *`?

为什么constexpr不会导致编译超出索引范围而失败

超出范围访问数组不会出错,为什么?

为什么Int类型2 ^ 31不会超出GHCi的范围?

为什么在不迭代的情况下调用迭代器函数时不会引发TypeError?

为什么main函数不能返回负数?

为什么我得到阶乘输出的负数?

为什么掩盖负数会产生正数?

JavaScript:为什么负数会返回正数?

为什么在SQL注入中使用负数?

为什么rand()+ rand()产生负数?

为什么总和的值变成负数?

为什么C支持负数组索引?

为什么函数会生成负数?

为什么用“&1”检查负数

为什么在代码开头插入C ++中的分号时不会显示任何错误?

为什么以“->”开头的行不会在Javascript中引发错误?

STL-为什么将范围解析运算符用于迭代器

为什么此迭代列表增长代码使IndexError:列表分配索引超出范围?

为什么标准迭代器范围是[begin,end]而不是[begin,end]?

为什么会出现运行时错误:向量擦除迭代器超出范围

为什么Golang在我的for循环中没有正确迭代范围?