Skip to content

Positional Members ​

You can let the caller pass some values as positional parameters to the starting function, that creates the builder or to the finishing function, that consumes it.

Starting function ​

Use #[builder(start_fn)] to move some members to the parameters of the starting function.

rust
use bon::Builder;

#[derive(Builder)]
// Top-level attribute to give a custom name for the starting function
#[builder(start_fn = with_coordinates)]                                
struct Treasure {
    // Member-level attributes to move members
    // to the parameters of `with_coordinates()`
    #[builder(start_fn)]                         
    x: u32,

    #[builder(start_fn)] 
    y: u32,

    label: Option<String>,
}

let treasure = Treasure::with_coordinates(2, 9) 
    .label("oats".to_owned())
    .build();

assert_eq!(treasure.x, 2);
assert_eq!(treasure.y, 9);
assert_eq!(treasure.label.as_deref(), Some("oats"));

TIP

There are two versions of the #[builder(start_fn)] used here: top-level and member-level. They have different meanings.

Finishing function ​

Use #[builder(finish_fn)] to move some members to the parameters of the finishing function.

rust
use bon::Builder;

#[derive(Builder)]
// Top-level attribute to give a custom name for the finishing function
#[builder(finish_fn = located_at)]                                      
struct Treasure {
    // Member-level attributes to move members
    // to the parameters of `located_at()`
    #[builder(finish_fn)]                      
    x: u32,

    #[builder(finish_fn)] 
    y: u32,

    label: Option<String>,
}

let treasure = Treasure::builder()
    .label("oats".to_owned())
    .located_at(2, 9);  

assert_eq!(treasure.x, 2);
assert_eq!(treasure.y, 9);
assert_eq!(treasure.label.as_deref(), Some("oats"));

TIP

There are two versions of the #[builder(finish_fn)] used here: top-level and member-level. They have different meanings.