Assosiated function with optinal values

Hello everyone,

I have a general question about structs and associated functions(or methods not sure what is what)

We can create a struct and a function to create it.

Like

struct Person {
name: String,
surname: String,
age: u32,
twitter: String,
facebook: String,
}

impl Person {
fn new(name: String, surname: String, age: u32, twitter: String, facebook: String) -> Self {
Self {name,surname,age,twitter,facebook}
}
}

let new_person = Person::new("John".to_string,"Ken".to_string, 32, "Twitter.com/elonmusk".to_string, "Facebook".to_string)

But let's say that name and surname are values that are presented all the time but things like age, Twitter and Facebook are optional.
In this case it will look something like this

struct Person {
name: String,
surname: String,
age: Option,
twitter: Option,
facebook: Option,
}

impl Person {
fn new(name: String, surname: String, age: Option, twitter: Option, facebook: Option) -> Self {
Self {name,surname,age,twitter,facebook}
}
}

So I will need to write it like this

let new_person = Person::new("John".to_string,"Ken".to_string, None, None, None)

Basically replacing with the None value all data that is optional.

it looks alright if there are not a lot of fields, but if for example there are 10-15 optional fields it can be a quite tedious job.

I know there is a way to create structs with a default value, but it will also require an fn to update this value for each field.

My question is: Is there any possibility to create a new::() function this way

if I write let new_person: Person::new(John, Kenn) - it will create data with only the name and surname field
But if I write let new_person: Person::(John, Kenn, 32) - it will create data with a name. surname, and age but twitter and facebook will be the default values.

Probably not since the compiler can't determine which string is related to what field. but worth a shot to ask.

Thanks

No, Rust does not allow default values for arguments, nor does it allow multiple dispatch (like Julia does for example). I find the struct update syntax is the closest thing Rust has to offer. Combined with Default, it looks very clean IMO:

#[derive(Default)]
struct Person {
    name: String,
    surname: String,
    age: Option<u32>,
    twitter: Option<String>,
    facebook: Option<String>,
}

fn main() {
    let _ = Person {
        name: "John".to_owned(),
        surname: "Kenn".to_owned(),
        age: Some(32),
        ..Default::default()
    };
}

There is also the builder pattern which you'll find often for instantiating complex structs:

#[derive(Default)]
struct Person {
    name: String,
    surname: String,
    age: Option<u32>,
    twitter: Option<String>,
    facebook: Option<String>,
}

impl Person {
    fn builder() -> PersonBuilder {
        PersonBuilder::default()
    }
}

#[derive(Default)]
struct PersonBuilder {
    person: Person,
}

impl PersonBuilder {
    fn with_name(mut self, name: impl AsRef<str>) -> Self {
        self.person.name = name.as_ref().to_owned();
        self
    }
    
    fn with_surname(mut self, surname: impl AsRef<str>) -> Self {
        self.person.surname = surname.as_ref().to_owned();
        self
    }
    
    fn with_age(mut self, age: u32) -> Self {
        self.person.age = Some(age);
        self
    }
    
    fn build(self) -> Person {
        self.person
    }
}

fn main() {
    let _ = Person::builder()
        .with_name("John")
        .with_surname("Kenn")
        .with_age(32)
        .build();
}
2 Likes

That looks great, thanks for the quick response!

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.