체인의정석

Rust 기본 프로그래밍 컨셉 (변수와 가변성) 본문

블록체인/Rust

Rust 기본 프로그래밍 컨셉 (변수와 가변성)

체인의정석 2023. 1. 16. 10:42
728x90
반응형

변수와 가변성 그리고 mut

먼저 변수를 한번 테스트 해보겠다.

➜ rust cargo new variables    
     Created binary (application) `variables` package

이런식으로 명령어를 내리게 되면 variables라는 경로가 나오게 된다.

 

fn main() {
    let x = 5;
    println!("The value of x is: {x}");
    x = 6;
    println!("The value of x is: {x}");
}

이런식으로 let으로 선언한 후 다시 접근하여 변수를 변경하려 할 경우 

error[E0384]: cannot assign twice to immutable variable `x`
 --> src/main.rs:4:5
  |
2 |     let x = 5;
  |         -
  |         |
  |         first assignment to `x`
  |         help: consider making this binding mutable: `mut x`
3 |     println!("The value of x is: {x}");
4 |     x = 6;
  |     ^^^^^ cannot assign twice to immutable variable

에러가 나게 된다.

여기서 알 수 있는 사실은 rust의 경우 컴파일 중간에 에러를 강력히 검사하여 에러가 미리 난다는 것이다.

solidity에서 직접 단위 테스트를 해야 하는 경우에 비하여 더 안전하다고 볼 수 있다.

 

만약 변수를 다시 수정하려 할 경우에는 mut을 통해 정의해 주면 된다.

fn main() {
    let mut x = 5;
    println!("The value of x is: {x}");
    x = 6;
    println!("The value of x is: {x}");
}

이렇게 넣고 돌리면

➜ variables (master) ✗ cargo run
   Compiling variables v0.1.0 (/Users/chohk/Desktop/git/rust/variables)
    Finished dev [unoptimized + debuginfo] target(s) in 0.26s
     Running `target/debug/variables`
The value of x is: 5
The value of x is: 6

변수값이 변하는 것을 볼 수 있다.

 

Const

 

두번째로 const이다.  constant는 바꿀 수 없는 변수이지만 var과는 다른 특징들이 있다.

우선 mut을 constants와 같이 사용할 수 없다. constants는 기본적으로 불변성을 가지고 있지 않으며 항상 불변성을 가지고 있다. 한마디로 let의 경우 mut을 쓰면 가변성이 생기지만 const의 경우 mut을 다시 쓸 수 가 없는 것이다.

 

또한 const의 경우 타입을 지정해 주어야 한다.

 

const의 경우 글로벌 변수까지 포함하여 어떠한 스코프에서든지 정의가 가능하다. 

 

마지막으로 const의 경우에는 함수의 결과 값으로 const를 변경할 수 없으며 오직 const로만 정의할 수 있다는 것이다.

 

const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;

이런식으로 정의가 가능하다는 말이다.

 

* 러스트의 네이밍 컨벤션은 const는 모두 대문자로 사용하고 단어 사이에는 '_'를 사용하는 것이다. 

 

 

Shadowing

세번째 알아야 할 부분은 첫번째 변수를 다시 한번 정의하는 경우 "Shadowing"이라고 부르는 부분이다.

fn main() {
    let x = 5;

    let x = x + 1;

    {
        let x = x * 2;
        println!("The value of x in the inner scope is: {x}");
    }

    println!("The value of x is: {x}");
}

위와 같이 let을 사용하여서 shadowing이 가능하다.

➜ variables (master) ✗ cargo run
   Compiling variables v0.1.0 (/Users/chohk/Desktop/git/rust/variables)
    Finished dev [unoptimized + debuginfo] target(s) in 0.28s
     Running `target/debug/variables`
The value of x in the inner scope is: 12
The value of x is: 6

프로그램에서 x를 처음에는 5로 묶어두지만 x+1로 만들어서 6이 나오게 한다. 그 후에 *2를 해서 12로 만든다.

이런식으로 shadowing을 해서 변수를 덮어쓰는 경우에는 mut와 다른점은 let 키워드를 다시 써주지 않는 이상 컴파일을 할 때 에러가 발생한다는 점에 있다. let 키워드를 사용하면 재정의가 가능하지만 그 순간에만 재정의가 가능한 것이다.

 

다른 차이점은 let 키워드를 사용한다는 것은 새로운 변수를 만드는 것이다.

따라서 let을 다시 shodowing하면 새로운 변수의 타입을 다시 정의할 수 있다. 

fn main() {
    let spaces = "   ";
    let spaces = spaces.len();
}

요런식으로 가능하다.

 

하지만 이를 mut으로 다시하게 되면 

fn main() {
    let mut spaces = "   ";
    spaces = spaces.len();
}

다음과 같이 오류가 나게 된다.

$ cargo run
   Compiling variables v0.1.0 (file:///projects/variables)
error[E0308]: mismatched types
 --> src/main.rs:3:14
  |
2 |     let mut spaces = "   ";
  |                      ----- expected due to this value
3 |     spaces = spaces.len();
  |              ^^^^^^^^^^^^ expected `&str`, found `usize`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `variables` due to previous error

 

이번 챕터를 배우면서 느낀 점은 일단 스코프에 다한 부분이 더 엄격하며

let과 const는 재정의를 하는 부분에 있어서의 차이가 있다는 점이다.

또한 타입에 대한 지정부분이 있는데 const는 강제로 지정해주어야 하며 let은 지정이 의무가 아니라는 점에서 차이가 있다는 점을 알았다.

 

컴파일 단계에서 이러한 점들을 잡아주다 보니 확실히 컨트렉트에서 사용하기 좋은 수준의 선언인것 같다.

 

출저 : https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html

728x90
반응형
Comments