Why does this work?

Way back last summer I sought help working with a vector that needed to accept generic types. I got a lot of help with that issue here. You all were very patient with me. I've been applying it and it's working, but, honestly, I still don't really understand what I'm doing with it. Here is a simplified snippet of code that might help me ask my question:

#[derive(Debug)]
struct Farm<T> {
    haystack: Vec<T>,
}

impl<T> Farm<T> {
    fn new() -> Farm<T> {
        Self {
            haystack: Vec::new(),
        }
    }
}

#[derive(Debug)]
enum TypeWrapper {
    Alphanum(Farm<String>),
    Unsigned(Farm<u64>),
    Integer(Farm<i64>),
    Floating(Farm<f64>),
    Letter(Farm<char>),
}

fn main() {
    let mut pasture = Farm::new();
    pasture.haystack = vec![2.5, -3.54, 78.1236];

    println!("\n An the vector is:    {:?}\n\n", pasture);
}

So, here's my question: I defined and implemented my Farm struct to accept a generic type and then created my enum to list the types I want to be using. In the main() function I use the struct, but nothing from the enum shows up. This works and I'm going to use it, but what am I doing? Clearly, I don't really understand how enums work or how this enum is interacting with my struct.

1 Like

You’re simply not using the enum in the main function in the code example you’ve provided

#[derive(Debug)]
struct Farm<T> {
    haystack: Vec<T>,
}

impl<T> Farm<T> {
    fn new() -> Farm<T> {
        Self {
            haystack: Vec::new(),
        }
    }
}

fn main() {
    let mut pasture = Farm::new();
    pasture.haystack = vec![2.5, -3.54, 78.1236];

    println!("\n An the vector is:    {:?}\n\n", pasture);
}

Rust Playground


Possibly you accidentally over-simplified your example though?

3 Likes

As you didn't specify the generic parameter T when creating new Farm, the compiler derives it from your assignment on following line:

pasture.haystack = vec![2.5, -3.54, 78.1236];

You 've added f64s into the vector haystack of type T, thus "T must be f64" for the pasture variable...

You can verify/see by looking at the implicit type annotations in IDE, eg. vscode :slight_smile:

this might be just my mis-interpretation of what you wrote, but to double check, this is what the current code conforms to:

  • Farm can accept generic type T
  • TypeWrapper specifies various types that do have Farm of some type inside of them

Is this what you wanted, or did you intend to define enum of types that can be added inside of the Farm rather?

#[derive(Debug)]
enum TypeWrapper {
    Alphanum(String),
    Unsigned(u64),
    Integer(i64),
    Floating(f64),
    Letter(char),
}

let mut pasture = Farm::new();
// i didn't specify type for pasture like:
//     let mut pasture = Farm::<TypeWrapper> = Farm::new();
// or like:
//     let mut pasture = Farm::<TypeWrapper>::new();
// so at this point of code, T could be "anything"

pasture.haystack = vec![TypeWrapper::Unsigned(123), TypeWrapper::Letter('a')];
// but this line "clearly" makes it `T == TypeWrapper,` for `pasture` 

// or, more succintly not to re-assign empty vector previously created inside of `::new()`:
let mut pasture = Farm { haystack: vec![TypeWrapper::Unsigned(123), TypeWrapper::Letter('a')] }
1 Like

Yes, I think you are correct here. The original issue (discussed last summer) centered around a set of three nested structs. The best solution seemed to be to use an enum similar to what I have here. Right now I have a somewhat different problem I'm trying to solve and in simplifying the problem I eliminated the need for the enum. I'm sure I will need to bring it back in eventually, but for now, I'm going to leave it out.

Thanks for your help, everyone! :clap: