How to return a tuple with impl?

enum Colors
{
    color{r:u8, g:u8, b:u8},
}
impl Colors
{
    
    fn return_values(&self) -> (u8, u8, u8)
    {
        (&self.r, &self.g, &self.b) // Error here
    }
    
}

fn main()
{
    let red = Colors::color{r: 255, g: 0, b: 0};
    println!("{}", red.return_values().0);
}

Not too sure how to return values as tuples under impl

Just remove the & inside the method body. This works because u8 is Copy. Note, not the & in the parameter list, just in the function body.

enum Colors
{
    color{r:u8, g:u8, b:u8},
}
impl Colors
{
    
    fn return_values(&self) -> (u8, u8, u8)
    {
        (self.r, self.g, self.b) // Error here
    }
    
}

fn main()
{
    let red = Colors::color{r: 255, g: 0, b: 0};
    println!("{}", red.return_values().0);
}

Is this what you mean? So this is what I did and I am still getting an error.

error[E0609]: no field `r` on type `&Colors`
  --> src\main.rs:10:15
   |
10 |         (self.r, self.g, self.b) // Error here
   |               ^

error[E0609]: no field `g` on type `&Colors`
  --> src\main.rs:10:23
   |
10 |         (self.r, self.g, self.b) // Error here
   |                       ^

error[E0609]: no field `b` on type `&Colors`
  --> src\main.rs:10:31
   |
10 |         (self.r, self.g, self.b) // Error here
   |                               ^

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0609`.
error: Could not compile `Learning`.

To learn more, run the command again with --verbose.

The issue is that only the color variant of Colors actually has the r, g and b fields. Consider the scenario where you add an extra variant:

enum Colors {
    // Enum variants should be capitalized!
    Color { r:u8, g:u8, b:u8 },
    Hsv { h: u8, s: u8, v: u8 },
}

What happens if you call return_values on a Colors::Hsv? That variant doesn't have the rgb fields, so your method no longer makes sense!

In order to make this work, you need to check which kind of Colors your instance of self is in the method:

fn return_values(&self) -> (u8, u8, u8) {
    match self {
        Colors::Color { r, g, b } => (r, g, b),
        Colors::Hsv { h, s, v } => (h, s, v),
    }
}

Now you're being explicit about where r, g and b come from, so everything should work!

Note however, that if you don't intent to add extra kinds of Colors, you're not really gaining anything by making it an enum - you could just use a struct like this:

struct Color {
    r: u8,
    g: u8,
    b: u8,
}

Your original impl would work fine on that struct, because every instance of it has the r, g and b fields.

3 Likes

I see.

I am not too sure how this match case works could you please elaborate on it?

Thanks for letting me know, I just wanted to learn enum but yeah sure I will keep that in mind :slight_smile:

I will strongly recommend to read The Book. I know, that you claim you did, but most of your questions are covered by it very clearly, this particular in two chapters: Enums matching and more detailed in Patterns syntax. Your exact question is actually fully answered in "Destructuring enums" example in the second of them. Its not like we don't want to help you, but it would safe both ours, but whats more important for you - your time, also book covers much more examples, than we can cover on forum in the same amount of text.

Oh I haven't read that yet and it seems like it is the next page after the 2nd page of enum chapter. Thanks for pointing that out to me.