I have just started to learn Rust
. During my first steps with this language, I found a strange behaviour, when an iteration is performed inside main
or in another function as in following example:
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);
}
While the loop in main
is correctly displayed, nothing is printed for the loop inside myfunc
and I get following output:
j: -1
j: 0
j: 1
j: 2
j: 3
j: 4
j: 5
n: 6
What is the cause of this behaviour?
Type inference is causing both of the numbers in your range to be usize
, which cannot represent negative numbers. Thus, the range is from usize::MAX
to n
, which never has any members.
To find this out, I used a trick to print out the types of things:
let () = -1 .. x.len();
Which has this error:
error: mismatched types:
expected `core::ops::Range<usize>`,
found `()`
(expected struct `core::ops::Range`,
found ()) [E0308]
let () = -1 .. x.len();
^~
Diving into the details, slice::len
returns a usize
. Your -1
is an untyped integral value, which will conform to fit whatever context it needs (if there's nothing for it to conform to, it will fall back to an i32
).
In this case, it's as if you actually typed (-1 as usize)..x.len()
.
The good news is that you probably don't want to start at -1
anyway. Slices are zero-indexed:
fn myfunc(x: &[f64]) {
let n = x.len();
println!(" n: {:?}", n);
for i in 0..n {
println!(" i: {}", i);
}
}
Extra good news is that this annoyance was fixed in the newest versions of Rust. It will cause a warning and then eventually an error:
warning: unary negation of unsigned integers will be feature gated in the future
for i in -1 .. n {
^~
Also note that you should never accept a &Vec<T>
as a parameter. Always use a &[T]
as it's more flexible and you lose nothing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With