-
-
Notifications
You must be signed in to change notification settings - Fork 24
#[builder(getter)]
full batteries mode
#225
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
Comments
@angelorendina you mentioned in #149 (comment) that you got Did you implement custom parsing of |
@Veetaha in my implementation attempt, I simply used |
Yeah, Just a headsup, I have a draft PR, that I'm currently working on for |
I'm revisiting the getters design for #[derive(bon::Builder)]
struct Command {
#[builder(start_fn)]
args: Vec<String>,
}
impl<S: command_builder::State> CommandBuilder<S> {
fn arg(mut self, arg: String) -> Self {
self.args.push(arg);
self
}
} The dilemma here is in the naming of the builder's field for the method's
Maybe the name has to be explicitly configured via |
I think one thing I would love to see is the ability to generate getters for all fields directly: #[derive(Builder)]
#[builder(on(_, getter))]
struct User {
name: String,
is_admin: bool,
level: Option<u32>,
} This currently generates an error. Also, I'm not sure if I'm misunderstanding the scope here, but will getters be accessible after the struct is built? The current implementation doesn't seem to do this, but I'm not sure if it's by design. |
I think having derive(Builder) isn't going to generate getters on the built struct, and this is by design. Otherwise it would be too surprising to see some other methods generated on the struct by derive(Builder) other than |
Yeah, I guess it's out-of-scope-ish for this crate. I just found out there's already a crate for this: https://github.com/jbaublitz/getset and it works well together with bon. |
Posting here since you asked for feedback. I am brand new to bon. Here is my use case: Builder roughly looks like: struct Cfg {
a: A,
b: B,
} I want to write a custom setter to allow the user to "derive" impl<S: cfg_builder::State> CfgBuilder<S> {
pub fn b_from_a(
self,
) -> CfgBuilder<cfg_builder::SetB<S>>
where
S::A: cfg_builder::IsSet,
S::B: cfg_builder::IsUnset,
{
let a = &self.a; // not possible! Unless maybe with the getters api?
let b = {
// some code that computes a `B` from `a`.
};
self.b(b)
}
} Importantly, the getter for Is this something that the getter feature would be intended for? Alternatively, perhaps just having a way to directly access the field would be sufficient? Again, I would want to have control over the field visibility, as ideally it is only directly accessible in this manner by |
Hi @TheButlah, I think for your use case it may be enough to set a default for field #[derive(bon::Builder)]
struct Cfg {
a: u32,
#[builder(default = a * 2)]
b: u32,
}
fn main() {
// Derive the value of `b` from `a` if `b` is not provided
let cfg = Cfg::builder().a(3).build();
assert_eq!(cfg.b, 6);
// Use the provided value of `b` if it is provided
let cfg = Cfg::builder().a(3).b(5).build();
assert_eq!(cfg.b, 5);
} For more advanced use cases I recommend defining a builder based on a function (function builder paradigm shift). Does this solution fit your problem? |
I think this would have worked, but in reality, my I just read the page you linked about the function builder paradigm shift, but I didn't understand how this applies here. Can you elaborate? |
More generally though, I think it is reasonable that custom setters should get access to any prior initialized values, via the |
@TheButlah I see, the fact that your struct Cfg {
a: u32,
b: u32,
}
#[bon::bon]
impl Cfg {
#[builder]
async fn new(a: u32, b: Option<u32>) -> Self {
let b = if let Some(b) = b {
b
} else {
// Do smth async to compute `b` based on `a` if `b` is not provided
async { a * 2 }.await
};
Self { a, b }
}
}
#[tokio::main]
async fn main() {
// Derive the value of `b` from `a` if `b` is not provided
let cfg = Cfg::builder().a(3).build().await;
assert_eq!(cfg.b, 6);
// Use the provided value of `b` if it is provided
// Unfortunately, the `build()` in this case is still async
let cfg = Cfg::builder().a(3).b(5).build().await;
assert_eq!(cfg.b, 5);
} You could also use However, if you want to be even more granular and explicit and have a sync signature you do need the getter feature to implement a custom async setter as you shown. So now I get your point, the |
OK, I will upvote the original post not because I actually want end-users to have access to the getters, but because I want access to the getters in my custom setters :P |
Understandable, using getters only privately in setters is one of the use cases I envisioned. Just make sure to mark the getters as private with |
…lds (#250) This is according to my design decision here: #225 (comment)
#[builder(getter)]
#[builder(getter)]
full batteries mode
I'm stabilizing the current MVP of this feature that's been in experimental state for 3 months: #251. The next minor version of I've renamed this issue to denote that what's left is to implement the rest of the batteries design as described in the issue body:
I've also implemented a change that makes the Now
These native private builder fields can be freely accessed in custom setters/getters or generally within the same module scope. |
It's been ~3 months since we've introduced an MVP of the `#[builder(getter)]` attribute, and the feature hasn't changed since its initial design. There are already some people using this API and asking to get it stabilized. I believe the current API design is already firm, and still amenable to the future extensions described in #225, so let's deploy this 🚀
This is a tracking issue for the
#[builder(getter)]
attribute feature. The stabilization of the design for this attribute requires some more feedback from the community.If you think the current design is already solid and covers your current or potential future use cases, then just leave a 👍 reaction.
If you'd like to change something about the
#[builder(getter)]
attribute syntax and behavior or just extend it, then feel free to leave a comment. We'd be glad to hear your ideas!Design Vision
Part of the following behaviors are already implemented, but not all.
Initial discussion on this attribute: #221
Checklist
&T
#[builder(start_fn)]
members#[builder(field)]
membersself
receiver of methodscopy
and by-clone
gettersderef(...)
configmut
getterswith
closure and shortgetter = closure
syntax)A note for the community from the maintainers
Please vote on this issue by adding a 👍 reaction to help the maintainers with prioritizing it. You may add a comment describing your real use case related to this issue for us to better understand the problem domain.
The text was updated successfully, but these errors were encountered: