Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
piratepilates
Mar 28, 2004

So I will learn to live with it. Because I can live with it. I can live with it.



I'm trying to learn some Rust since it seems like a pretty rad idea, so far I've been trying to do some simple data structures to figure it all out.

Here's what I have for a binary search tree, it compiles and runs but the insertion doesn't fully work -- it seems to remove all the past changes each time you insert a new node:

http://is.gd/qhiZkq
code:
fn main() {
    let mut butt = BSTNode::new(5);
    println!("{:?}", butt);
    butt.insert(7);
    println!("{:?}", butt);
    butt.insert(2);
    println!("{:?}", butt);
    butt.insert(1);
    butt.insert(3);
    butt.insert(4);
    butt.insert(6);
    butt.insert(8);
    println!("{:?}", butt);

}

#[derive(Debug)]
struct BSTNode {
    value: i32,
    left: Option<Box<BSTNode>>,
    right: Option<Box<BSTNode>>
}

impl BSTNode {
    fn new(value: i32) -> BSTNode {
        BSTNode {
            value: value,
            left: None,
            right: None
        }
    }
    
    fn insert(&mut self, value: i32) {
        match (self.value > value, self.left.take(), self.right.take()) {
            (true, None, _) => self.left = Some(Box::new(BSTNode::new(value))),
            (true, Some(ref mut left), _) => left.insert(value),
            (false, _,  None) => self.right = Some(Box::new(BSTNode::new(value))),
            (false, _, Some(ref mut right)) => right.insert(value),
        }
    }
}
Which prints:

code:
BSTNode { value: 5, left: None, right: None }
BSTNode { value: 5, left: None, right: Some(BSTNode { value: 7, left: None, right: None }) }
BSTNode { value: 5, left: Some(BSTNode { value: 2, left: None, right: None }), right: None }
BSTNode { value: 5, left: None, right: None }
Anyone know how I screwed up?

Also how far off base is everything I did idiomatically-wise?

Also what exactly is 'self.left.take()' doing? It fails compiling without it with the message 'cannot move out of borrowed content' and I somehow googled my way in to using it.

edit: alright well scratch why it doesn't work, take() just replaces the content with a None, which is why my children are disappearing. How do I borrow the self.left and self.right in the match otherwise?

Adbot
ADBOT LOVES YOU

piratepilates
Mar 28, 2004

So I will learn to live with it. Because I can live with it. I can live with it.



Gaukler posted:

I'm quite new to Rust myself so I spent some time wrestling the borrow checker, but the following works: (http://is.gd/nVAEU0)

code:
fn main() {
    let mut butt = BSTNode::new(5);
    println!("{:?}", butt);
    butt.insert(7);
    println!("{:?}", butt);
    butt.insert(2);
    println!("{:?}", butt);
    butt.insert(1);
    butt.insert(3);
    butt.insert(4);
    butt.insert(6);
    butt.insert(8);
    println!("{:?}", butt);

}

#[derive(Debug)]
struct BSTNode {
    value: i32,
    left: Option<Box<BSTNode>>,
    right: Option<Box<BSTNode>>
}

impl BSTNode {
    fn new(value: i32) -> BSTNode {
        BSTNode {
            value: value,
            left: None,
            right: None
        }
    }
    
    fn insert(&mut self, value: i32) {
    
        if self.value > value {
            match self.left {
                Some(ref mut left) => left.insert(value),
                None => self.left = Some(Box::new(BSTNode::new(value))),
            }
        } else {
            match self.right {
                Some(ref mut right) => right.insert(value),
                None => self.right = Some(Box::new(BSTNode::new(value))),
            }
        }
    }
}
Prints:
code:
BSTNode { value: 5, left: None, right: None }
BSTNode { value: 5, left: None, right: Some(BSTNode { value: 7, left: None, right: None }) }
BSTNode { value: 5, left: Some(BSTNode { value: 2, left: None, right: None }), right: Some(BSTNode { value: 7, left: None, right: None }) }
BSTNode { value: 5, left: Some(BSTNode { value: 2, left: Some(BSTNode { value: 1, left: None, right: None }), right: Some(BSTNode { value: 3, left: None, right: Some(BSTNode { value: 4, left: None, right: None }) }) }), right: Some(BSTNode { value: 7, left: Some(BSTNode { value: 6, left: None, right: None }), right: Some(BSTNode { value: 8, left: None, right: None }) }) }
Which looks right by my checking. I THINK the problem was when you do (self.value > value, self.left, self.right), you implicitly create a new Tuple which borrows self.left and self.right, so you can't use them in your match arms.

Sounds good to me, thanks.

piratepilates
Mar 28, 2004

So I will learn to live with it. Because I can live with it. I can live with it.



You've got some real problems if you read that and parse it as anything other than "be nice to people, don't be a dick"

piratepilates
Mar 28, 2004

So I will learn to live with it. Because I can live with it. I can live with it.



Alright so I'm learning Rust again, and I'm trying to make a program that modifies images. I'm making a function that takes an image and returns a copy of that image that is grayscale, but I can't get it to compile yet.

Here's what I have so far:

(The image library is the piston image library (https://github.com/PistonDevelopers/image)
code:
extern crate image;

use std::fs::File;
use std::path::Path;

fn grayscale_image_buffer(input_image: image::ImageBuffer) -> image::ImageBuffer {
    let (image_x, image_y) = input_image.dimensions();

    image::ImageBuffer::from_fn(image_x, image_y, |x, y| {
        let pixel = input_image.get_pixel(x, y);
        let r = pixel.data[0] as f32;
        let g = pixel.data[1] as f32;
        let b = pixel.data[2] as f32;
        let average = (r + g + b) / 3.0;
        image::Luma([average as u8])
    })
}
Now this complains about not having the right number of arguments to ImageBuffer in the parameter and return types, which makes sense since it's a generic container of <Pixel, Container>.

If I change the function to be generic I get this:

code:
extern crate image;

use std::fs::File;
use std::path::Path;

fn grayscale_image_buffer<P, C>(input_image: image::ImageBuffer<P, C>) -> image::ImageBuffer<image::Luma<u8>, C> {
    let (image_x, image_y) = input_image.dimensions();

    image::ImageBuffer::from_fn(image_x, image_y, |x, y| {
        let pixel = input_image.get_pixel(x, y);
        let r = pixel.data[0] as f32;
        let g = pixel.data[1] as f32;
        let b = pixel.data[2] as f32;
        let average = (r + g + b) / 3.0;
        image::Luma([average as u8])
    })
}
Which gives the error "error: the trait `image::buffer::Pixel` is not implemented for the type `P`
[E0277]{" on the function definition line.

Making the function definition read like "fn grayscale_image_buffer<P: image::Pixel, C>" just gives me more errors about, well, everything. Can't find methods for the image passed in that I know exist on ImageBuffer, mismatched types, "error: the type of this value must be known in this context".

Basically all hell breaks loose and I'm not sure what the compiler is expecting of me at this point. What am I missing to make this function work?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply