Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Special-case tuples into multiple arguments #184

Open
typedrat opened this issue May 17, 2024 · 1 comment
Open

Special-case tuples into multiple arguments #184

typedrat opened this issue May 17, 2024 · 1 comment

Comments

@typedrat
Copy link

Currently, if you have your constructor take a tuple argument, the builder function requires a tuple. I'm using that to represent multiple values that don't make sense to set independently, but it would be a little bit cleaner if the methods on the builder took multiple arguments, one for each member of the tuple, rather than a tuple itself.

@polarathene
Copy link

polarathene commented Jun 5, 2024

You can specify a separate method for your builder to use instead of new(args: (x, y ,z)).

You could then have your individual parameters as an alternative method that internally returns Self::new(args):

#[derive(Debug)]
struct Language {
    name: String,
    id: u32,
    favourite: bool,
}

#[buildstructor::buildstructor]
impl Language {
    pub fn new(args: (String, u32, bool)) -> Self {
        Self {
            name: args.0,
            id: args.1,
            favourite: args.2,
        }
    }

    // Not `pub fn`, so it's private/hidden while the builder method will be public:
    #[builder(entry = "builder", exit = "build", visibility="pub")]
    fn from_args(name: String, id: u32, favourite: bool) -> Self {
        Self::new((name, id, favourite))
    }
}

fn main() {
    let lang = Language::builder()
        .name("Rust")
        .id(42)
        .favourite(true)
        .build();

    println!("{lang:#?}");
}
$ cargo run

Language {
    name: "Rust",
    id: 42,
    favourite: true,
}

You were a bit vague on the issue and what the ideal solution would look like with buildstructor, so I may have misunderstood 😅


UPDATE: Perhaps you were requesting the builder to abstract away the need for wrapping args as a tuple type for the generated parameter method, but internally still map as a tuple?

I have raised that feature request here (it seems to be partially supported already for collections): #187

// NOTE: Below is just an example, not actually supported yet

#[derive(Debug)]
struct Language {
    name: String,
    id: u32,
    favourite: bool,
}

#[buildstructor::buildstructor]
impl Language {
    #[builder]
    pub fn new(args: (String, u32, bool)) -> Self {
        Self {
            name: args.0,
            id: args.1,
            favourite: args.2,
        }
    }
}

fn main() {
    // Instead of tuple wrapped single-arg `.args(("Rust", 42, true))`,
    // take each as a separate arg to `.args()` instead:
    let lang = Language::builder()
        .args("Rust", 42, true)
        .build();

    println!("{lang:#?}");
}

In the linked example I have a Pair<X, Y>(X, Y) / Pair<String, String> type where having the separate values as individual args might make more sense for the feature than the example I adapted above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants