zzz6519003 / blog

My blog about coding
4 stars 1 forks source link

rust thoughts of an execerise (What do you think is the more commonly used pattern under Rust developers?) #155

Open zzz6519003 opened 1 year ago

zzz6519003 commented 1 year ago
// vecs2.rs
// A Vec of even numbers is given. Your task is to complete the loop
// so that each number in the Vec is multiplied by 2.
//
// Make me pass the test!
//
// Execute `rustlings hint vecs2` or use the `hint` watch subcommand for a hint.

// I AM NOT DONE

fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
    for i in v.iter_mut() {
        // TODO: Fill this up so that each element in the Vec `v` is
        // multiplied by 2.
        println!("{}",i);
        *i = *i * 2;
    }

    // At this point, `v` should be equal to [4, 8, 12, 16, 20].
    v
}

fn vec_map(v: &Vec<i32>) -> Vec<i32> {
    v.iter().map(|num| {
        // TODO: Do the same thing as above - but instead of mutating the
        // Vec, you can just return the new number!
        num * 2
    }).collect()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_vec_loop() {
        let v: Vec<i32> = (1..).filter(|x| x % 2 == 0).take(5).collect();
        let ans = vec_loop(v.clone());

        assert_eq!(ans, v.iter().map(|x| x * 2).collect::<Vec<i32>>());
    }

    #[test]
    fn test_vec_map() {
        let v: Vec<i32> = (1..).filter(|x| x % 2 == 0).take(5).collect();
        let ans = vec_map(&v);

        assert_eq!(ans, v.iter().map(|x| x * 2).collect::<Vec<i32>>());
    }
}
zzz6519003 commented 1 year ago

hint Hint 1: i is each element from the Vec as they are being iterated. Can you try multiplying this?

Hint 2: For the first function, there's a way to directly access the numbers stored in the Vec, using the * dereference operator. You can both access and write to the number that way.

After you've completed both functions, decide for yourself which approach you like better. What do you think is the more commonly used pattern under Rust developers?

zzz6519003 commented 1 year ago

second question:

hint So, vec0 is passed into the fill_vec function as an argument. In Rust, when an argument is passed to a function and it's not explicitly returned, you can't use the original variable anymore. We call this "moving" a variable. Variables that are moved into a function (or block scope) and aren't explicitly returned get "dropped" at the end of that function. This is also what happens here. There's a few ways to fix this, try them all if you want:

  1. Make another, separate version of the data that's in vec0 and pass that to fill_vec instead.
  2. Make fill_vec borrow its argument instead of taking ownership of it, and then copy the data within the function in order to return an owned Vec<i32>
  3. Make fill_vec mutably borrow a reference to its argument (which will need to be mutable), modify it directly, then not return anything. Then you can get rid of vec1 entirely -- note that this will change what gets printed by the first println!