I found this code from 'Programming Rust' book, and I'm a little confusing about it. Take a look at this code:
fn main() {
let v: Vec<i32> = vec![1, 2, 3];
let temp = 1;
for &val in v[3..].iter() {
println!("{}", val);
println!("{}", gcd(val, temp));
}
println!("hello world");
}
fn gcd(mut n: i32, mut m: i32) -> i32 {
assert!(n != 0 && m != 0);
while m != 0 {
if m < n {
let t = m;
m = n;
n = t;
}
m = m % n;
}
n
}
The highest index of the vector is 2. But why this code is not error(but if change v[4..] the error is pop out). If call the next method after consume all value the it return None but why the rust analyzer show the type of val is i32 and not None, I tried to print it but nothing come out. Even can pass in the function. Is that a null? Why rust allow this code?
A half-open range starting and ending one past the end of the vector does not include the last element (since it is an empty range). Therefore it is allowed. It is also allowed for symmetry and ease of use so that slice[0..slice.len()] is the same as slice[..].
You in the line for &val in v[3..].iter() since you said no value is copy, but type of val is i32 so I can pass it in the function println!("{}", gcd(val, temp); . So val has no value but have the type i32? Are no value and Null difference?
Code still has to pass the type checker whether it is ever executed or not. In the line for &val in v[3..].iter(), val has the type i32 because v[3..] has the type [i32], but that does not mean that valever actually contains an i32.
This is a useful property because it means the compiler can compile the code correctly without knowing what it will actually do at runtime. The compiler does not know, when compiling that line, that v[3..] is an empty slice. This is a good thing because if the correct way to compile the code depended on whether the slice was empty or not, a lot of code wouldn't be compilable at all.