The struct update syntax


#1

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”);


#2

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).


#3

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:


#4

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


#5

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.