Hello,

I have a problem with creating a mutable nested data structure when combined 
with functions.
I’m lost in all those &muts, boxes and lifetimes. :-)

I would like to crawl a directory looking for subdirectories and in those 
subdirectories find all images.
So I started with a vector for holding those subdirectories.
Then I created a struct to hold a directory path and a vector of images.
Also a struct for the image itself.

It all works in one function body but not when refactored into functions.
I understand that when a variable is sent as an argument, the ownership is 
moved so it cannot be used after the function call.
So I sent &-references instead but then it would yell at me that borrowed 
things are not mutable.
So I &mut-ed it all and it would yell that lifetimes are not defined.
So I tried to define lifetimes but then it would say that things do not live 
long enough. This is where I stopped.
I also tried the box-way but that yells about immutable dereference. I’m not 
even sure I have those boxes right.

This is the code:
(Also available here https://gist.github.com/ollie/9c81d2a368bf7bf0831a, there 
is also a Ruby version not listed here.)


With references and lifetimes:

#[deriving(Show)]
struct Image {
    filename: String,
}

#[deriving(Show)]
struct Section<'a> {
    path:   String,
    images: &'a mut Vec<Image>,
}

impl Image {
    fn new(filename: &str) -> Image {
        Image {
            filename: String::from_str(filename),
        }
    }
}

impl<'a> Section<'a> {
    fn new(path: &str) -> Section {
        Section {
            path:   String::from_str(path),
            images: &mut Vec::new(),
        }
    }

    fn add_image(&mut self, image: Image) {
        self.images.push(image);
    }
}

fn read_directories(sections: &mut Vec<&mut Section>) {
    let dirs = ["./dir-a", "./dir-b"];

    for dir in dirs.iter() {
        let mut section = &mut Section::new(*dir);
        read_images(section);
        sections.push(section);
    }
}

fn read_images(section: &mut Section) {
    let files = ["./image-1.png", "./image-2.png"];

    for file in files.iter() {
        section.add_image(Image::new(*file));
    }
}

fn main() {
    let mut sections = Vec::new();
    read_directories(&mut sections);
    println!("{}", sections);
}



With boxes:

#[deriving(Show)]
struct Image {
    filename: String,
}

#[deriving(Show)]
struct Section {
    path:   String,
    images: Box<Vec<Image>>,
}

impl Image {
    fn new(filename: &str) -> Image {
        Image {
            filename: String::from_str(filename),
        }
    }
}

impl Section {
    fn new(path: &str) -> Section {
        Section {
            path:   String::from_str(path),
            images: box Vec::new(),
        }
    }

    fn add_image(&mut self, image: Image) {
        self.images.push(image);
    }
}

fn read_directories(sections: Box<Vec<Box<Section>>>) {
    let dirs = ["./dir-a", "./dir-b"];

    for dir in dirs.iter() {
        let mut section = box Section::new(*dir);
        read_images(section);
        sections.push(section);
    }
}

fn read_images(section: Box<Section>) {
    let files = ["./image-1.png", "./image-2.png"];

    for file in files.iter() {
        section.add_image(Image::new(*file));
    }
}

fn main() {
    let mut sections = box Vec::new();
    read_directories(sections);
    println!("{}", sections);
}



All in one, no referenes and lifetimes:

#[deriving(Show)]
struct Image {
    filename: String,
}

#[deriving(Show)]
struct Section {
    path:   String,
    images: Vec<Image>,
}

impl Image {
    fn new(filename: &str) -> Image {
        Image {
            filename: String::from_str(filename),
        }
    }
}

impl Section {
    fn new(path: &str) -> Section {
        Section {
            path:   String::from_str(path),
            images: Vec::new(),
        }
    }

    fn add_image(&mut self, image: Image) {
        self.images.push(image);
    }
}

fn main() {
    let mut sections = Vec::new();
    let dirs         = ["./dir-a", "./dir-b"];

    for dir in dirs.iter() {
        let mut section = Section::new(*dir);
        let files       = ["./image-1.png", "./image-2.png"];

        for file in files.iter() {
            section.add_image(Image::new(*file));
        }

        sections.push(section);
    }

    println!("{}", sections);

    // [
    //   Section {
    //     path: ./dir-a,
    //     images: [Image { filename: ./image-1.png }, Image { filename: 
./image-2.png }]
    //   },
    //   Section {
    //     path: ./dir-b,
    //     images: [Image { filename: ./image-1.png }, Image { filename: 
./image-2.png }]
    //   }
    // ]
}


I’ve read the tutorial, the rust-by-example site but it still feels alien to 
me. :-/

Thank you,
Ollie
_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to