Rust course Lesson 4 of 6

Rust from zero: a method can change the struct

A method with &mut self changes the struct. add_tip adds 20 percent to a $4.50 bill, and the program prints $5.40.

Piere is one of GoByte's characters. This post was drafted by AI agents in Piere's voice, then fact checked, run and edited by the GoByte team.

Back to top

label borrowed the struct and did not change it. A method that adds a tip needs &mut self, a mutable borrow. The caller marks the bill mut as well. Both sides agree the object can change. Twenty percent of 450 cents is 90, so the bill becomes 540 cents, which is $5.40.

&mut self is permission to write#

&self borrows the struct for reading. &mut self borrows it for writing, and Rust allows only one mutable borrow at a time. add_tip needs the mutable borrow because it writes cents. The binding in main is let mut bill because the owner must agree to be mutated before anyone can borrow it that way. 450 * 20 / 100 is integer arithmetic. The division happens after the multiply, so the tip is 90 cents and not a float.

The same bill, after the tip
  1. start450
  2. add_tip(20)540
struct Bill {
    cents: i32,
}

impl Bill {
    fn add_tip(&mut self, percent: i32) {
        self.cents += self.cents * percent / 100;
    }
}

fn main() {
    let mut bill = Bill { cents: 450 };
    bill.add_tip(20);
    println!("${}.{:02}", bill.cents / 100, bill.cents % 100);
}
$5.40

mut is written where the change happens#

Bill { cents: 450 } starts at the price of the latte. let mut bill says the bill may change. fn add_tip(&mut self) says the method may change the fields. self.cents += self.cents * percent / 100 adds the tip onto that field. One call prints $5.40.

If you drop mut from let, the call bill.add_tip(20) does not compile, because add_tip asks for a mutable borrow. If you write &self instead of &mut self, the assignment does not compile. The compiler is telling you which side forgot to allow the change.

One mutable borrow at a time#

While add_tip runs, it holds the mutable borrow. You do not also read bill.cents from main in the middle of that call. The call ends, the borrow ends, and println! reads the new total. That rule is why a Rust object is easier to reason about than a value everyone can write at once. The next lesson uses an enum when a value is one of several cases.

Report a mistake

Your product here? Partner with us

Back to top

Discussion

No comments yet. Signed in GoByte members with a verified e-mail can join. Community guidelines

Reading is open to everyone. Commenting and voting need a GoByte account with a verified e-mail.