456c526f
456c526f

Reputation: 133

Iterate over Vec<"CustomStruct"> => unsatisfied trait bounds

I'm participating in this year's Advent of Code and wanted to take the opportunity to learn Rust. (So, if you're also participating, the following section might spoil something).

I want to iterate over the Vec vector and decrement the internal_counter value for each Item in this Vector. I tried the following: let test: Vec<Lanternfish> = fish_list.map(|fish| fish.decrement_couner()).collect();

The compiler gives me the following error: method cannot be called on Vec<Lanternfish> due to unsatisfied trait bounds I understand that the iterator function is not available for this, however I don't understand exactly how to fix the problem.

#[derive(Debug)]
struct Lanternfish {
    internal_counter: u8,
}

impl Lanternfish {
    fn new() -> Self {
        Lanternfish {
            internal_counter: 8,    
        }
    }

    fn decrement_counter(&mut self) {
        self.internal_counter -= 1
    }
}

fn part_one(content: &str) {
    let content: Vec<char> = content.chars().filter(|char| char.is_digit(10)).collect();   
    let mut fish_list: Vec<Lanternfish> = init_list(content);

    let test: Vec<Lanternfish> = fish_list.map(|fish| fish.decrement_counter()).collect();
}

fn init_list(initial_values: Vec<char>) -> Vec<Lanternfish> {
    let mut all_lanternfish: Vec<_> = Vec::new();
    for value in initial_values {
        all_lanternfish.push(Lanternfish{internal_counter: value as u8});
    }
    all_lanternfish
}

Upvotes: 0

Views: 842

Answers (1)

Sebastian Redl
Sebastian Redl

Reputation: 72054

The way to iterate over a Vec and call a mutating function on each element is:

for fish in &mut fish_list {
  fish.decrement_counter();
}

What this line is doing:

fish_list.map(|fish| fish.decrement_couner).collect();

is

  • Try to call map on the Vec (it doesn't have that. Iterator has it, but you'd need to call iter(), iter_mut() or into_iter() on the Vec for that).
  • Assuming you get the right map, it then calls the lambda |fish| fish.decrement_couner on each element; typo aside, this is not a function call, but a field access, and Lanternfish doesn't have a field called decrement_couner. A call would need parentheses.
  • Assuming you fix the function call, you then collect all the results of the calls (a bunch of () "unit" values, since decrement_counter doesn't return anything) into a new Vec, which is of type Vec<()>.
  • And finally, you try to bind that to a variable of Vec<Lanternfish>, which will fail.

Meanwhile, the function calls will have modified the original Vec, if you used iter_mut(). Otherwise, the function calls will not compile.

Upvotes: 2

Related Questions