Oldřich Vetešník
2014-09-10 14:05:12 UTC
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140910/bee6a64e/attachment.html>
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140910/bee6a64e/attachment.html>