This is a piece from the cook book. I don't know what the * in *elem -6 does, please see the comments down below. Thanks.
extern crate ndarray;
use ndarray::Array;
fn main() {
let a = Array::from_vec(vec![1., 2., 3., 4., 5.]);
let b = Array::from_vec(vec![5., 4., 3., 2., 1.]);
let z = a + b;
let mut c = Array::from_vec(vec![1., 2., 3., 4., 5.]);
let mut d = Array::from_vec(vec![5., 4., 3., 2., 1.]);
let w = &c + &d;
let epsilon = 1e-8;
for elem in z.iter() {
println!("elem is {}", elem); //don't need * here
let diff: f32 = *elem - 6.; //without * there is a type mismatch between f32 and f64
assert!(diff.abs() < epsilon);
}
println!("c is {}", c);
c[0] = 10.;
d[1] = 10.;
for elem in w.iter() {
let diff: f32 = *elem - 6.;
assert!(diff.abs() < epsilon);
}
.iter() iterates by reference. That is, instead of giving you directly a number from the array, it gives you a reference: "the number you want is over there".
* is a dereferencing operator. When you have a reference, * on it takes the value the reference is pointing to.
Rust automatically does this in many situations, like calling methods. But sometimes you need to nudge it to say you want to subtract numbers, not reference to a number.
In your case you can use .iter().cloned() which instead of references to numbers in the array will copy them out and give actual numbers (copying of numbers is super cheap, so that makes sense for arrays of integers or floats).
Ah, yes. Rust is picky about type conversions. Conversions between f32/f64 influence program speed and precision of calculations, so Rust wants to force programmers to think exactly where these conversions take place.
number as f32 (or *num_ref as f32) will give you the right type.
I experimented and found another interesting / tricky feature that I don't remember I've seen in the book.
let epsilon = 1e-8;
for elem in z.iter() {
let diff: f64 = elem - 6.; //why not use f64. works with or w/o *
assert!(diff.abs() < epsilon);
}
println!("c is {}", c);
c[0] = 10.;
d[1] = 10.;
for elem in w.iter() {
let diff: f32 = *elem - 6.; //now this will not work
assert!(diff.abs() < epsilon);
}
so when I changed the type of diff in the first loop, the second stops working. basically,
let x = 1.0;
let y: f32 = x; //ok
let z: f64 = x; //fails
It's like floating point type is determined the first time it's used. What is it called?
For numerics, it's not just floating point, it's integers as well. If you're using literals and want to be precise about their type right when they're written, you can append the type to the literal - e.g. 1.0f32 or 1.0f64 (similarly for integers: 1u64 or 1i8, etc). If you're using a let binding, you can ascribe the type similarly, i.e. let x: f32 = 1.0. I know some people who prefer to use type annotations in most of their code, although most Rust code that I've seen makes heavy use of inference.