I’m trying to learn Rust and am using the advent of code to do so. I’ve just started and have decided to have a vector containing "Elf" structs, of which each will contain a vector calory_items.
I’m trying to create this from a text file and have the following code:
use std::io::{self, BufReader};
use std::path::Path;
use std::io::prelude::*;
use std::fs::File;
struct Elf {
calory_items: Vec<i32>
}
fn parse_meal_list(source: &str) -> Vec<Elf> {
let file = File::open(source).unwrap();
let file = BufReader::new(file);
let mut elves: Vec<Elf> = Vec::new();
let mut elf = Elf {
calory_items: Vec::new()
};
for line in file.lines() {
let line = line.unwrap();
if line.is_empty() {
// create new Elf
if elf.calory_items.len() > 0 {
// in case there are two empty lines
elves.push(elf);
let mut elf: Elf = Elf { calory_items: Vec::new() };
}
} else {
// append to current Elf object the calories
let calory_item: i32 = line.parse().unwrap();
elf.calory_items.push(calory_item)
}
}
return elves;
}
fn main() {
let input_day_1_source = Path::new("input_files/day_1.txt");
let input_day_1_source = input_day_1_source.to_str().unwrap();
let Elves: Vec<Elf> = parse_meal_list(input_day_1_source);
}
The compiler gives me the following error:
error[E0382]: borrow of moved value: `elf`
--> src/main.rs:23:16
|
15 | let mut elf = Elf {
| ------- move occurs because `elf` has type `Elf`, which does not implement the `Copy` trait
...
19 | for line in file.lines() {
| ------------------------ inside of this loop
...
23 | if elf.calory_items.len() > 0 {
| ^^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
24 | // in case there are two empty lines
25 | elves.push(elf);
| --- value moved here, in previous iteration of loop
I read the Rust book about the borrow checker but don’t know how I can append an item to the list and return the ownership (or solve it another way).
>Solution :
I assume that with:
let mut elf: Elf = Elf { calory_items: Vec::new() };
You intended to initialize elf with an empty Elf again. But this does not do what you want. Instead, it creates a separate variable that shadows elf, making it inaccessible for the rest of the block but does not change the original elf variable. You need to use assignment:
elf = Elf { calory_items: Vec::new() };