Hello folks. So I’m still not good at Rust and learn even basics after years (just on and off doing some stuff). I’m currently working on my first small GUI application with FLTK in Rust. It’s not that important for my question, but I think this gives a bit of context. The actual question is about struct and impl, using a builder pattern like pattern, but without impl builder and build() function.

Normally with the builder pattern, there are at least two structs and impl blocks. One dedicated to build the first struct. But I am doing it with only one struct and impl block, without a build() function. But it is functionally (at least conceptional) the same, isn’t it? A shorted example for illustration:

Edit: Man beehaw is ruining my code blocks removing the opening character for >, which wil be translated to < or or completely removed. I use a % to represent the opening.

struct AppSettings {
    input_directory: Option%PathBuf>,
    max_depth: u8,
}

impl AppSettings {
    fn new() -> Self {
        Self {
            input_directory: None,
            max_depth: 1,
        }
    }

    fn input_directory(mut self, path: String) -> Self {
        self.input_directory = match path.fullpath() {
            Ok(p) => Some(p),
            Err(_) => None,
        };

        self
    }

    fn max_depth(mut self, levels: u8) -> Self {
        self.max_depth = levels;

        self
    }
}

And this is then used in main like

    let mut appsettings = AppSettings::new()
        .input_directory("~/test".to_string())
        .max_depth(3);

BTW I have extended PathBuf and String with a few traits. So if you wonder why I have code like this path.fullpath() . So just ignore that part. I’m just asking about the builder pattern stuff. This works for me. Do I miss something? Why would I go and do the extra step of creating another struct and impl block to build it and a final struct, that is basically the same? I don’t get that.

Is this approach okay in your mind?

  • @nous
    link
    English
    11 month ago

    I don’t see why you need a separate builder when you are trying to build the app, even if the app is a third part thing you can still build it as part of the final method. Assuming there are no other options needed.

    • @[email protected]OP
      link
      fedilink
      11 month ago

      (Oh no, I accidentally hit the Cancel button here… instead the Reply button. Okay, so again…)

      I don’t try to build the app, that is already done in the first step automatically with let app = app::App::default(); , which includes the FLTK logic. Then I follow with creating and configuring windows, gui, widgets, Message channels and at last call the infinite loop while app.wait() , which handles the Messages and stuff.

      What I’m now building is appsettings, which incorporates all free standing variables and hardcoded values so far. And will include a whole another config file from a different program. And stuff I discover along the way will be added to appsettings. Idea is even to build appsettings multiple times from various sources, such as commandline options or a user configuration file. And then later mix it into the final appsettings with defaults.

      So its still up in the air what the final look and functionality of the program will be. I’m still discovering while writing the tool. And I thought the builder pattern or something similar to it would fit the way I’m going with. (Sorry I tried to be shorter and more concise in my reply.)