Mut와 Shadowing

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이 발견됐다는 에러가 표시됩니다.

let문은 ;으로 끝나야 하는데, ;이 없어 에러가 남

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를 제거하라는 도움말이 표시됩니다.

가변 변수가 아닌데, mut가 붙어 있어서 경고 메시지가 표시되고, 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개를 사용해야 해서 매우 번거롭습니다.