-
Notifications
You must be signed in to change notification settings - Fork 89
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
Idea: Let the builder wrap a Result<T,Error> #25
Comments
That's a very nice proposal. Thank you. :-) Some minor adjustment:
What could be the syntax?
|
Perhaps the user should be required to name of the builder, so that the names don't clash when two builders are defined in the same module.
|
Regarding errors, I would probably prefer to fail fast and get the first error. That behavior is similar to On a slightly related note here isa much more general idea, but I am not sure if it can even be implemented in a beautiful way, and I am not fully sure if it could work with the existing builder, but nevertheless: Given the following code
It could be great to derive the following code could be derived behind the scenes
The idea is to wrap each method with a method that updates the Result. |
I like the general idea, but I would like from more people in need / favour of this before implementing something like that. :-) |
Would this approach satisfy the use-case? Allow opt-in generation of #[derive(Builder)]
#[builder(setter(into))]
pub struct Person {
name: String,
#[builder(try_setter)]
age: Age,
#[builder(try_setter)]
mail: Mail,
}
// This would be a struct but I'm lazy and didn't want to write the method bodies.
trait PersonBuilder {
fn name<VALUE: Into<String>>(&mut self, value: VALUE) -> &mut Self;
fn age<VALUE: Into<Age>>(&mut self, value: VALUE) -> &mut Self;
fn try_age<VALUE: TryInto<Age>>(&mut self, value: VALUE) -> Result<&mut Self, VALUE::Err>;
fn mail<VALUE: Into<Mail>>(&mut self, value: VALUE) -> &mut Self;
fn try_mail<VALUE: TryInto<Mail>>(&mut self, value: VALUE) -> Result<&mut Self, VALUE::Err>;
fn build(self) -> Result<Person, String>;
}
fn make_person_with(name: &str, age: usize, address: String) -> Result<Person, Error> {
PersonBuilder::default()
.try_age(age)?
.try_mail(address)?
.name(name)
.build()
.map_err(Into::into)
} Advantages:
If there's a blanket |
Interesting proposal. I like the comparably low implementation footprint and self-documenting generated api. :-) I'm trying to organize the builder attributes in namespaces like On the other hand, if we do introduce it as something like |
This is a good point, and probably a case for a second attribute. I like |
Cool. Importantly only the generated code would need nightly, which means, that only the integration test should have this problem. The crate |
Working on this now. I was initially thinking this should be a separate attribute, but I can't think of a good reason why |
We need to decide how the API should look like (a) Piggy-back style allows us to share settings like visibility and basename. Shared settings are easier to implement and probably sufficient in most cases. The current implementation in PR #72 already uses shared settings, which would match with the piggy-back style API. One thing that is especially nice, is the synchronization of name changes. If you change the setter name to The stand-alone style makes it much more clear what's happening as opposed to Can we get the best of both worlds? Let's call it loosely coupled style: We can start Does that make sense? |
Works for me, I'm having a hard time coming up with a valid case for any of those properties being different for the try_setter, but I do like the fact that it's clear this creates a second method. |
Ok, cool. We can start without any additional options on However in the future a use case could be this combination |
Just released v0.4.4 with fallible setters implemented by @TedDriggs 🎉 Thank you! :-) |
Here is a loose idea. It is mostly meant as an inspiration..
It could be to have a builder that wraps a Result. This would allow the builder to validate fields during the build process, and keep track of errors. Rust already allows you to do this with the
try!()
, macro, and the ?-operator has been accepted as RFC 243, but I still think that it could be nice to have a builder that keeps track of errors.Here is what the code could look like
Here is the code that could be derived behind the scenes
The text was updated successfully, but these errors were encountered: