4 ms·
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 i
by codeflo 5y ago
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, but that's in my experience rare in the Rust community.
- kevincox 5y agoThis pattern is fairly good but doesn't support required arguments.
- seritools 5y agoYou can mix-and-match, e.g. 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)
- estebank 5y agoI 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_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).
- ahupp 5y agoThis old RFC came up elsewhere in the thread and sounds like a similar idea: https://github.com/rust-lang/rfcs/pull/1806 https://github.com/rust-lang/rfcs/pull/1806
- shepmaster 5y ago> assumes that String::new will be const at some point It has been const since Rust 1.39 (https://doc.rust-lang.org/std/string/struct.String.html#method.new https://doc.rust-lang.org/std/string/struct.String.html#meth...)
- brundolf 5y agoOT, but how can a value that lives on the heap be const? And how could ownership of a (non-Copy) const be passed somewhere else?
- codeflo 5y agoThe 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.
- brundolf 5y agoBut 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?
- codeflo 5y agoAh, 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_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 }
- deleted 5y ago[deleted]