What an augmented assignment is
Changing a variable based on its own value is one of the most common things a program does. The long way to add 5 to my_var is:
my_var = my_var + 5;
Rust evaluates the right side of = first and then stores the result in the variable on the left. Because this pattern is so common, Rust has a shorter form that does the operation and the assignment in one step, called an augmented assignment (or compound assignment):
let mut my_var = 10;
my_var += 5;
println!("{}", my_var); // 15
There is one such operator for each arithmetic operator:
| Operator | Meaning | Example | Result |
|---|---|---|---|
+= | x = x + y | 10 then x += 5 | 15 |
-= | x = x - y | 10 then x -= 5 | 5 |
*= | x = x * y | 3 then x *= 5 | 15 |
/= | x = x / y | 20 then x /= 4 | 5 |
%= | x = x % y | 11 then x %= 3 | 2 |
Rust details to know
The variable must be mutable
Variables in Rust are immutable by default, and an augmented assignment changes the variable. So it has to be declared with let mut. Without mut, the compiler stops with an error:
error[E0384]: cannot assign twice to immutable variable `x`
The fix is to write let mut x = 1;.
Integer division drops the remainder
When both sides are integers, /= uses integer division. With let mut x = 7;, the statement x /= 2; leaves 3, not 3.5. With a float, let mut f = 7.0; followed by f /= 2.0; gives 3.5. The right side must have the same type as the variable: you cannot write x /= 2.0 on an integer.
Other types
Augmented assignment is not only for numbers. A String supports += with a &str on the right: after let mut s = String::from("ab"); and s += "cd";, the string s holds abcd.
Overflow
The result has to fit in the variable's type. An i32 holds values up to 2,147,483,647. In a debug build, going past a type's range panics. In an optimized build (-O), which is how these lessons are compiled, the value wraps around silently. For example, with a u8 holding 255, x += 1 leaves 0 in an optimized build.
The whole right side is evaluated first
The expression on the right of an augmented assignment is computed completely before it is combined with the variable. So w *= 3 + 1 multiplies w by 4, not by 3: with w equal to 2, the result is 8. In the same way, v -= n * 2 with v equal to 5 and n equal to 3 leaves -1.
Where you will use them
The most common use is a running total. Inside a loop, total += price adds each value to total. Starting from 0 and adding 3, 4 and 5 leaves 12. Doubling a value repeatedly with *= 2 is another typical pattern: starting from 2 and doubling twice leaves 8.
The exercise, step by step
The exercise is a drill: start from a number and apply one augmented assignment at a time. Work out the value after each step, because the last step depends on it.
- Create the variable.
let mut number: i32 = 18;Themutis needed because every later step changesnumber. - Add 8 with
+=. The value is now 26. - Subtract 1 with
-=. The value is 25. Rust has no--operator, so-= 1is the way to decrement. - Divide by 5 with
/=. Both sides are integers, and 25 divides evenly, so the value is 5. - Add 1 with
+=. The value is 6. - Multiply by 3 with
*=. The value is 18. - Subtract 18 with
-=. The value goes back down to 0.
Together:
let mut number: i32 = 18;
number += 8;
number -= 1;
number /= 5;
number += 1;
number *= 3;
number -= 18;
Each line is a complete statement and ends with a semicolon. Adding println!("{}", number); after any line shows the values listed above.
Common mistakes
- Forgetting
mut. This is the most frequent error with these operators. - Reversing the symbols. The operator character comes first:
+=is valid,=+is not an augmented assignment.x =+ 5meansx = +5, and Rust does not even accept a unary plus in front of a number. - Using
--or++. They do not exist in Rust. Use-= 1and+= 1. - Expecting a fraction from integer
/=.26 / 5is5. Only the quotient is kept. - Losing track of the value. After several steps, the current value is easy to misjudge. Write it next to each line, as in the list above.
Key takeaways
x op= yis shorthand forx = x op y.- Rust provides
+=,-=,*=,/=and%=. - The variable needs
let mut. - With integers,
/=keeps only the quotient.
