Mut는 “변수의 값을 바꿀 수 있다(mutable)”는 의미이고, Shadowing은 “같은 변수명을 사용해서 이전의 변수를 가리는” 기능입니다. Shadowing을 통해 Mut의 기능을 대체할 수도 있고, 둘 다 사용하지 않는다면 변수명을 여러 개 사용해야 하는 번거로움이 있습니다.
1. Mut를 사용한 경우
아래 예시는 x를 mutable(가변) 변수로 선언한 다음
=> let mut x = 9;
x의 값을 바꿔가면서 원하는 값인 final_number를 출력하는 코드입니다.
=> x = times_two(x);
=> x = x + y;
이 때 반환값은 x라고 ;없이 씁니다.
fn times_two(number: i32) -> i32 {
number * 2
}
fn main() {
let final_number = {
let y = 10;
let mut x = 9;
x = times_two(x);
x = x + y;
x
};
println!("The number is now:{}", final_number);
}
그러나, let final_number가 끝나는 지점에는 let 문이므로 ;을 반드시 붙여야 합니다. 안 붙이면 아래와 같이 ;을 기대했는데, println이 발견됐다는 에러가 표시됩니다.

Rust의 특이한 점이 불변(immutable)이 변수의 기본 상태이고, 변수의 값을 바꿀 수 있게 하려면 mut를 붙여야 한다는 점입니다.
※ 함수 구문
fn times_two(number: i32) -> i32 {
number * 2
}
Rust에서 함수를 선언할 때는 fn을 사용하고 그 다음에 함수명을 붙이는 것은 다른 언어와 같습니다.
그 다음 괄호 안에 인수명을 입력하는데, 여기서는 number이고,
반드시 인수의 타입을 입력해야 하는데, : 다음에 i32 식으로 “32비트 부호 있는 정수” 타입이라고 명시합니다.
이것이 변수의 경우 추론(inference)이 돼서 타입을 반드시 기재해야 할 필요가 없는 것과 다른 점입니다. 변수의 경우 정수는 i32, 실수는 f64가 기본형입니다.
그리고, 반환 값이 있으면 반환 값의 형식도 입력해야 하는데,
-> 다음에 i32식으로 입력합니다.
따라서, 반환값이 없으면 ‘-> 반환 값 형식’을 입력하지 않습니다.
그리고, 중괄호 안에 함수의 내용을 기록하고, 반환값을 마지막에 입력하는데, 여기서는 반환값이 number * 2로 인수에 2를 곱한 값을 반환하는 것인데, 마지막에 ;을 붙이지 않는 것도 중요한 점의 하나입니다.
2. Shadowing을 사용한 경우
Shadowing은 “그림자처럼 따라 다님”이란 의미이므로, 여기서는 원래 있던 x 변수를 가리는 역할을 합니다.
Shadowing을 이용하게 되면 x = 을 let x =이라고 쓰고,
처음 변수 선언할 때 mut 없이 let x = 9;이라고 씁니다.
fn times_two(number: i32) -> i32 {
number * 2
}
fn main() {
let final_number = {
let y = 10;
let x = 9;
let x = times_two(x);
let x = x + y;
x
};
println!("The number is now:{}", final_number);
}
만약 let mut x = 9;라고 mut를 붙여도 결과는 같지만,
‘변수가 mutable일 필요가 없다”는 경고와
mut를 제거하라는 도움말이 표시됩니다.

3. shadowing과 mut를 사용하지 않은 경우
fn times_two(number: i32) -> i32 {
number * 2
}
fn main() {
let final_number = {
let y = 10;
let x = 9;
let twice_x = times_two(x);
let twice_x_and_y = twice_x + y;
twice_x_and_y
};
println!("The number is now:{}", final_number);
}
1과 2 예제에서는 변수명으로 x 하나만을 사용했는데,
이번 예제 3에서는 x, twice_x, twice_x_and_y라는 변수 3개를 사용해야 해서 매우 번거롭습니다.