Builder Pattern in Rust
71–80 of 93 posts
Re: Builder Pattern in Rust
#72> 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...
What bugs me a bit about Rust is the lack of default parameters. Even with the Default trait, the caller still has to write a bit of boilerplate ( ..Default::default()). 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
#73Re: Builder Pattern in Rust
#74Personally I think if you need a builder, you did something wrong in the first place. If you have a struct with so many defaultable values, you should break it into smaller pieces. Reasonable struct should not need more than 5 properties, unless it's something like ORM mapping of database table.
Besides, breaking structures in smaller structures this way can lead to code that's much harder to follow, refactor, and maintain.
Re: Builder Pattern in Rust
#75Earlier quoted context omitted.
The trick is that an empty string doesn’t actually own any data on the heap. It’s basically a null pointer, and all string methods check for that in some way. This is a typical optimization trick that many languages implement (empty lists and strings are very common). Defining new to be const just makes this optimization a requirement.
But still- at a language semantics level, values can't have multiple owners, and String couldn't implement Copy just for this one case. So how does this reconcile with the borrow-checker? Or can consts have multiple owners since they're immutable and have a static lifetime? Is this just the first case of a non-Copy being const, so the question has never come up before?
Statics, in contrast, have a storage location and a static lifetime.
Compare:
const CONST_STRING: String = String::new();
static STATIC_STRING: String = String::new();
fn main() {
let x: String = CONST_STRING; // fine
let y: String = STATIC_STRING; // error: cannot move out of static item
}Re: Builder Pattern in Rust
#76Earlier quoted context omitted.
But still- at a language semantics level, values can't have multiple owners, and String couldn't implement Copy just for this one case. So how does this reconcile with the borrow-checker? Or can consts have multiple owners since they're immutable and have a static lifetime? Is this just the first case of a non-Copy being const, so the question has never come up before?
Ah, I get your question now, I thought you were talking about const functions. Well, const values in Rust are funny things, they're not linked into the executable, they don't have an address or a lifetime. That confused me too for a while. They're purely a shortcut for a value expression, not that different from a #define in C. Statics, in contrast, have a storage location and a static lifetime. Compare: const CONST_…
Re: Builder Pattern in Rust
#77Earlier quoted context omitted.
This solution works sometimes, but it's not great if any of the fields don't have a sensible default.
You end up having to do struct Parameters { non_optional_parameter_1: Foo, non_optional_parameter_2: Bar, extra_options: ParametersWithDefault, } #[derive(Default)] struct ParametersWithDefault { ... } which is kind of annoying but not the end of the world.
use module::{ foo, Parameters, ParametersWithDefault };
fn bar() {
foo(Parameters {
non_optional_parameter_1: Foo,
non_optional_parameter_2: Bar,
extra_options: ParametersWithDefault {
optional_param: Baz,
...Default::default(),
}
});
}
is a far cry in ergonomics from: use module::foo;
fn bar() {
foo(_ {
non_optional_parameter_1: Foo,
non_optional_parameter_2: Bar,
optional_param: Baz,
..
});
}
Even just having to import the extra structs (and lookup the names) is a massive pain. Especially if you need to change to use a slightly different function.Re: Builder Pattern in Rust
#78Earlier quoted context omitted.
What bugs me a bit about Rust is the lack of default parameters. Even with the Default trait, the caller still has to write a bit of boilerplate ( ..Default::default()). 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?
Default parameters, optional parameters, and named parameters kind of form this massive design space where they all sorta kinda influence each other, and so while there hasn't been a formal "yes" or "no" directly from the team about these features, they tend to get caught up in a combination of "there are bigger issues to worry about" along with the combinatorial explosion of truly exploring the design space, at leas…
Re: Builder Pattern in Rust
#79Earlier quoted context omitted.
What bugs me a bit about Rust is the lack of default parameters. Even with the Default trait, the caller still has to write a bit of boilerplate ( ..Default::default()). 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?
> Are there better ways It's a question of taste, but the builder pattern can be considered a “better way”, because of how clunky the use of Default can be. You would prefer an API with easier to read, documented builders than the ..Default::default() call.
Re: Builder Pattern in Rust
#80In a relevant sense, common occurrence of a pattern reveals a weakness in the language where it appears, because no one has succeeded in capturing it in a library so it doesn't need to be coded again. Thus, C programs are shot through with hash table implementations, because a generally usable hash table library is not possible in C. Rust has a good one in the standard library, so Rust programs with a custom hash tab…
what's wrong with C that you cannot design a general-purpose hash table? Is it that you cannot define a general-purpose function to hash an object and check for equality?