First, I want to wish everyone well during these trying times. I also am hoping to bring some good news. I am trying to put a little Rust in my work mix
This crate is/will be used to generate urls specific to a service we provide at work. Day to day I'm tackling stuff like this in java, ruby, python, +. However, after being influenced by ripgrep, cargo, et al. I find builder-patterned interfaces to be much more configurable than say a telescoping constructor pattern in java.
I was hoping to get some feedback here. Are builder interfaces really as convenient as I feel they are for configuring interfaces? What other patterns would you suggest?
I only have one qualm with the builder pattern, I really like to const things if I can.
The instances of the builder pattern that I have seen, require the builder to be mut, even when the thing it is actually building could be. In these cases if you can't opt out of it, it can get in the way.
Not that I have really found a good replacement, and I'm not sure how many/much of your urls it might be possible use with const.
I unfortunately haven't been able to find a pattern that is as convenient and works with const .
Thanks! Yeah, you're right. You're also right about there not really being a replacement. In one text on the subject that's one of the consequences of using the pattern.
I'm still trying to
find a pattern that is as convenient and works with const
But where I've settled for now is trying to enforce strong semantics about what it means for the structure to be in a valid state at each step of the process. Maybe there's a solution where this pattern gets exposed along with a pattern that allows for a more const or immutable friendly option.
Maybe I could write Builder where the building functions take self and return a newly constructed Builder { --snip-- } then write a BuilderMut that takes mut self during construction and mutates the current struct and returns the mutated form... Hmmm.
So you could implement Default for your type and people override the fields they care about, then use ..Default::default() to fill in the rest using Foo's Default implementation.
This is really great information, thank you! And yeah, that's what I was getting with
functions take self and return a newly constructed Builder { --snip-- }
E.g. fn field(self, f: String) -> Self { ... } , but alas functional update syntax is the right set of words to describe the goal here (especially since selfcould be omitted entirely). Thank You!