홈강좌Rust 입문·중급 47편 중 3편째
Rust 변수 — let 은 바꿀 수 없고, 바꿀 것만 mut 를 붙인다
Rust 에서 let 으로 만든 변수는 값을 바꿀 수 없다. 다시 대입하면 E0384 오류로 컴파일이 멈춘다. 값을 바꿀 변수에만 mut 를 붙이고, 프로그램 내내 그대로인 값은 const 로 둔다.
01 let 으로 만든 변수는 바꿀 수 없다
let 이름 = 값; 이 변수를 만드는 문장이다. println! 의 따옴표 안에 {이름} 을 쓰면 그 자리에 변수의 값이 찍힌다. 카운터를 하나 올리는 코드를 다른 언어 습관대로 쓰면 이렇게 된다.
fn main() {
let count = 0;
println!("count = {count}");
count = count + 1;
println!("count = {count}");
} Compiling counter v0.1.0 (~/projects/counter)
error[E0384]: cannot assign twice to immutable variable `count`
--> src/main.rs:4:5
|
2 | let count = 0;
| ----- first assignment to `count`
3 | println!("count = {count}");
4 | count = count + 1;
| ^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
|
help: consider making this binding mutable
|
2 | let mut count = 0;
| +++
For more information about this error, try `rustc --explain E0384`.
error: could not compile `counter` (bin "counter") due to 1 previous error2편에서 익힌 세 군데로 읽는다.
- 무엇 — 바꿀 수 없는(immutable) 변수
count에 두 번 대입했다. - 어디 — 4번째 줄이다. 처음 값을 넣은 2번째 줄도 함께 짚어 준다.
- 고치는 법 —
let뒤에mut를 넣으라고 한다.
02 바꿀 변수에만 mut 를 붙인다
시키는 대로 mut 를 붙이면 컴파일되고 값이 바뀐다.
fn main() {
let mut count = 0;
println!("count = {count}");
count = count + 1;
println!("count = {count}");
} Compiling counter v0.1.0 (~/projects/counter)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.16s
Running `target/debug/counter`
count = 0
count = 1기본이 "못 바꿈" 인 것은 읽기 쉬워서다. mut 가 없는 변수는 끝까지 처음 값 그대로라고 컴파일러가 보장한다. 코드를 읽다가 이 값이 어디서 바뀌었는지 찾아다닐 일이 없다. TypeScript 에서 let 보다 const 를 먼저 쓰는 습관과 비슷하다.
반대로 바꾸지도 않을 변수에 mut 를 붙이면 경고가 나온다.
fn main() {
let mut name = "Ferris";
println!("Hello, {name}!");
} Compiling greeting v0.1.0 (~/projects/greeting)
warning: variable does not need to be mutable
--> src/main.rs:2:9
|
2 | let mut name = "Ferris";
| ----^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` (part of `#[warn(unused)]`) on by default
warning: `greeting` (bin "greeting") generated 1 warning (run `cargo fix --bin "greeting" -p greeting` to apply 1 suggestion)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.16s
Running `target/debug/greeting`
Hello, Ferris!warning 은 error 와 달리 컴파일을 막지 않는다. 그래서 마지막 줄에 Hello, Ferris! 가 찍혔다. 그래도 help: remove this mut 대로 지우는 편이 좋다. mut 는 "이 값은 바뀐다" 는 표시라서, 안 바뀌는 변수에 붙어 있으면 읽는 사람을 속인다.
03 절대 안 바뀌는 값은 const
최대 시도 횟수처럼 프로그램 내내 그대로인 값은 상수 const 로 둔다.
const MAX_TRIES: u32 = 3;
fn main() {
let mut tries = 1;
println!("{tries}/{MAX_TRIES}");
tries = tries + 1;
println!("{tries}/{MAX_TRIES}");
} Compiling login v0.1.0 (~/projects/login)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.52s
Running `target/debug/login`
1/3
2/3const 에는 규칙이 셋 있다.
- 타입을 꼭 적는다.
: u32가 타입 표기인데, 타입은 5편부터 하나씩 다룬다. - 이름은 대문자와 밑줄로 쓴다(
MAX_TRIES). - 함수 밖에도 둘 수 있다. 위처럼 맨 위에 두면 파일 어디서나 쓴다.
04 실습 — 오류를 먼저 예상해 보기
아래 코드를 돌리기 전에, 어느 줄에서 무슨 오류가 날지 먼저 짐작해 보자.
fn main() {
let score = 80;
score = 90;
println!("{score}");
}짐작했으면 돌려 본다.
error[E0384]: cannot assign twice to immutable variable `score`
--> src/main.rs:3:5
|
2 | let score = 80;
| ----- first assignment to `score`
3 | score = 90;
| ^^^^^^^^^^ cannot assign twice to immutable variable
|
help: consider making this binding mutable
|
2 | let mut score = 80;
| +++score 에 mut 가 없으니 3번째 줄에서 이 편 처음과 같은 E0384 가 났다. let mut score = 80; 으로 고치면 90 이 찍힌다. 다음 편에서는 mut 없이 같은 이름을 다시 쓰는 방법, 가림(shadowing)을 다룬다.
05 자주 묻는 질문
const 와 mut 없는 let 은 무엇이 다른가?
둘 다 못 바꾸지만, const 는 타입을 꼭 적고 컴파일할 때 정해지는 값만 담는다. let 은 실행 중에 계산한 값도 담을 수 있다.