The builder pattern is not an alternative for named arguments. It's just too verbose, and it handles non-optional arguments poorly. There are libraries for generating a builder with the typestate pattern that can ensure that .finish()
can't be called before all non-optional values were provided, but I don't like pulling in a dependency for this.
To avoid the boilerplate, I usually crate an Options
struct instead:
#[derive(Default)]
pub struct CompileOptions {
foo: Foo,
bar: Bar,
baz: Baz,
}
So people can call compile(CompileOptions { foo: Foo, ..Default::default() })
. But this is still boilerplate, and also can't handle non-optional arguments, if the struct implements Default
. It's also more cumbersome to use because the user has to import the Options
type.