The struct update syntax

I'm currently learning the rust basics from "The Book (2nd edition)" and I've just found out that it's possible to use this 'struct update' shortcut for duplicating fields from another struct .

let user2 = User {
    email: String::from("another@example.com"),
    username: String::from("anotherusername567"),
    ..user1
};

I'm curious what are the experienced rustaceans thinking about this syntax : are you using it frequently ? do you ... like it ?

I understand that the feature can be useful when duplicating a struct with many fields and you set only a few of them , but the syntax itself looks so weird ...

Would it be ok (from a coding style point of view) to prefer doing this instead ?

let user2 = user1.clone();
user2.email = String::from("another@example.com");
user2.username = String::from("anotherusername567");

1 Like

I personally use the struct update syntax a lot - especially with .. Default::default() when I want most of the parameters to be their default values.

However I think the second example you gave is also perfectly readable. The only disadvantage I can think of is that it's three statements instead of one, and might be more brittle under refactoring as a result.

EDIT: Another issue is that to use the second method - your let binding must be mutable (you're missing a mut there). The first method will allow you to ensure that your struct is immutable after construction (or until moved).

1 Like

Don't worry, most "syntax is looking weird" stops after a few weeks into learning any new language. It's kind of like learning Greek or Russian - a new alphabet always looks strange at first :slight_smile:

2 Likes

Worth noting that this syntax has precedent in Javascript and probably other languages. I use it pretty often in Rust.

I like to use it when defining methods for a builder. For example:

struct Something {
  field1: T,
  field2: T,
  field3: T,
}

impl<T> Something<T> {
  pub fn new() -> Self {/*code*/}

  pub fn field1 (self, field_value: T) -> Self {
    Something {field1: field_value, ..self}
  }

  pub fn field2 (self, field_value: T) -> Self {
    Something {field2: field_value, ..self}
  }
}

This is one way of using the builder pattern that is very convenient if you have a large struct with a lot of fields.

2 Likes