Builder::build argument type convention

I noticed that I did something apparently unconventional when I wrote my last builder. I made the configuration methods take &mut self, but the terminal method self. Do you think that is an acceptable pattern?

The API guidelines have two different types of builders:

  • non-consuming: &mut self for configuration, &self for the terminal method
  • consuming: mut self for configuration, self for terminal method

What do you think about my pattern, &mut self with self terminal? At least superficially it seems legitimate, you have a builder, you configure it by mutating its fields, and finally consume it without having to clone anything …?

I guess the reason that people rarely do that is that this wont compile:

let foo = Builder::new()
    .configure_bar()
    .build();

Exactly.

And that's why my usual advice (@glts) is to just take (and return) self by value in the configuration methods as well. In this case you can't accidentally reuse the builder, but method chaining still works.

Alternatively, if you do want to be able to reuse a configured builder, then build() should probably take &self.

cascade - crates.io: Rust Package Registry
https://crates.io/crates/cascade

This is not an advice but FYI: builders taking &mut self can be written in similar way to method chaining, by cascade! macro by cascade crate.
(Thanks to this macro, I think it is primarily important whether the builder can be reused or not, rather than whether it is easy to write or not.)

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.