Just add default / optional / named parameters to the language and be done with it.
Builder Pattern in Rust
21–30 of 93 posts
Re: Builder Pattern in Rust
#22I appreciate the tradeoffs that led to the builder pattern becoming commonplace, but it's probably my least favorite part of Rust. Compared to optional named parameters it just feels clunky, verbose and kind of Java-esque.
IMO, the toy example in the article is too simple to show a good use of the pattern. The builder pattern is great if the builder methods configure complicated invariants and are not just setters. Otherwise, there's nothing wrong with making the struct public, as in User { id, email, ..Default::default() } What's Java-esque is having an irrational fear of using public fields for things that are just data containers, b…
Re: Builder Pattern in Rust
#23Earlier quoted context omitted.
IMO, the toy example in the article is too simple to show a good use of the pattern. The builder pattern is great if the builder methods configure complicated invariants and are not just setters. Otherwise, there's nothing wrong with making the struct public, as in User { id, email, ..Default::default() } What's Java-esque is having an irrational fear of using public fields for things that are just data containers, b…
This pattern is fairly good but doesn't support required arguments.
new(required_arg_1, required_arg_2, Options { foo: "bar", ..Default::default() })
or Options { foo: "bar", ..Default::default() }).build(required_arg_1, required_arg_2)Re: Builder Pattern in Rust
#24I appreciate the tradeoffs that led to the builder pattern becoming commonplace, but it's probably my least favorite part of Rust. Compared to optional named parameters it just feels clunky, verbose and kind of Java-esque.
I agree. I’ve seen a few libraries (I can’t remember which) instead take the approach of a constructor that takes a single-use struct as an argument. The struct implements Default and all of its members are public. You can then use ..Struct::default() to splice in the default values, and override only the values you want to set. It ends up being an approximation of named optional arguments, albeit with a somewhat mor…
Re: Builder Pattern in Rust
#25Earlier quoted context omitted.
IMO, the toy example in the article is too simple to show a good use of the pattern. The builder pattern is great if the builder methods configure complicated invariants and are not just setters. Otherwise, there's nothing wrong with making the struct public, as in User { id, email, ..Default::default() } What's Java-esque is having an irrational fear of using public fields for things that are just data containers, b…
This pattern is fairly good but doesn't support required arguments.
struct User {
id: Id,
email: EMail,
name: String = String::new(),
age: u16 = 0,
}
let user = User { id, email, .. }; // valid
let user = User { id, .. }; // complain about email missing
It would leverage `const` expressions, so it would desugar effectively to the same as if you had written: const DEFAULT_USER_NAME: String = String::new();
const DEFAULT_USER_AGE: u16 = 0;
struct User {
id: Id,
email: EMail,
name: String,
age: u16,
}
let user = User { id, email, name: DEFAULT_USER_NAME, age: DEFAULT_USER_AGE };
The above assumes that String::new will be const at some point (it can be).If this ever lands, then there will be less need to write Builder traits by hand.
Also, at some point the free-standing `default()` function that calls `Default::default()` will land, making it that much shorter to write (without any new features like I'm proposing).
Re: Builder Pattern in Rust
#26Earlier quoted context omitted.
I would quite like to see some syntax sugar around this. If we could elide the type and made `...` equivalent to `..Default::default()` it would be a lot closer to kwargs without having to introduce any new "real" features. So we could write: f(arg1, arg2, _ {name: "Hello", address, ...}) instead of f(arg1, arg2, MyKwargs {name: "Hello", address, ..Default::default()} Using a struct for this feels natural as you get…
I would like this plus the ability to specify per-field defaults on structs like struct Foo { bar: String, // No default baz: Option = None, } I think this would give us 90% of what I would want from first-class named parameters.
If you're interested, this is the last public conversation I had about these: https://internals.rust-lang.org/t/pre-pre-rfc-syntactic-suga...
Re: Builder Pattern in Rust
#27Earlier quoted context omitted.
This pattern is fairly good but doesn't support required arguments.
I haven't filed an RFC yet, but I have a plan that I'm optimistic can land sometime that would let you write: struct User { id: Id, email: EMail, name: String = String::new(), age: u16 = 0, } let user = User { id, email, .. }; // valid let user = User { id, .. }; // complain about email missing It would leverage `const` expressions, so it would desugar effectively to the same as if you had written: const DEFAULT_USER…
Re: Builder Pattern in Rust
#28> Since we do not have default arguments in Rust, in order to initialize such structure we would have to list all fields: I'm surprised the article doesn't mention Default: https://doc.rust-lang.org/std/default/trait.Default.html It can be combined with the rest pattern to yield something very similar to the solution the author is after. https://stackoverflow.com/questions/19650265/is-there-a-fast...
The caller needs to know that the input struct implements Default.
And you would need one input struct per function (if default values differ).
Are there better ways or is it planned to introduce something like default parameters?
Re: Builder Pattern in Rust
#29Earlier quoted context omitted.
This pattern is fairly good but doesn't support required arguments.
I haven't filed an RFC yet, but I have a plan that I'm optimistic can land sometime that would let you write: struct User { id: Id, email: EMail, name: String = String::new(), age: u16 = 0, } let user = User { id, email, .. }; // valid let user = User { id, .. }; // complain about email missing It would leverage `const` expressions, so it would desugar effectively to the same as if you had written: const DEFAULT_USER…
It has been const since Rust 1.39 (https://doc.rust-lang.org/std/string/struct.String.html#meth...)