변수(Variables)
Rust에서는 let 키워드를 사용하여 변수를 선언합니다. 예를 들어 다음과 같이 작성할 수 있습니다.
let x = 42;
위 코드는 x라는 이름의 변수를 정의하고, 여기에 42라는 값을 할당한 것입니다.
타입(Type)
Rust의 모든 변수는 타입을 가져야 합니다. 컴파일러가 상황을 보고 타입을 알아서 **추론(Inference)**하거나, 개발자가 직접 **명시(Annotation)**할 수 있습니다.
명시적 타입 어노테이션(Explicit Type Annotation)
변수 이름 뒤에 콜론 :과 타입을 추가하여 변수의 타입을 직접 지정할 수 있습니다.
// let <변수_이름>: <타입> = <표현식>;
let x: u32 = 42;
위 예제에서는 x의 타입을 u32로 명시했습니다.
타입 추론(Type Inference)
타입을 직접 적지 않으면, 컴파일러는 변수가 어떻게 사용되는지 보고 타입을 추론합니다.
let x = 42;
let y: u32 = x;
위의 예에서 x에는 타입을 지정하지 않았지만, 나중에 u32 타입인 y에 할당됩니다. Rust는 타입을 자동으로 바꿔주지(Implicit coercion) 않으므로, 컴파일러는 x의 타입을 u32로 추론하게 됩니다. 이것이 프로그램이 오류 없이 컴파일될 수 있는 유일한 길이기 때문입니다.
추론의 한계
컴파일러가 주변 맥락만으로는 타입을 정확히 알아내지 못할 때도 있습니다. 이럴 때는 컴파일 오류가 발생하며, 컴파일러는 개발자에게 명시적으로 타입 힌트를 달아달라고 요청하게 됩니다.
함수 매개변수(Function parameters)도 변수입니다
모든 변수가 let으로만 선언되는 것은 아닙니다. 함수 매개변수도 결국 변수와 같습니다!
fn add_one(x: u32) -> u32 {
x + 1
}
위 예제에서 x는 u32 타입의 변수입니다. let 변수와 한 가지 다른 점이 있다면, 함수 매개변수는 타입을 반드시 명시해야 한다는 것입니다. 컴파일러가 대신 추론해주지 않거든요. 덕분에 컴파일러(와 우리 인간!)는 함수 안의 코드를 일일이 들여다보지 않고도 함수의 시그니처만 보고 어떤 역할을 하는지 바로 이해할 수 있습니다. 이는 컴파일 속도를 높이는 데에도 큰 도움이 됩니다1!
초기화(Initialization)
변수를 선언할 때 꼭 바로 값을 넣어줄 필요는 없습니다.
let x: u32;
이렇게 선언만 하는 것도 가능합니다. 다만, 해당 변수를 실제로 사용하기 전에는 반드시 초기화해야 합니다. 그렇지 않으면 컴파일러가 다음과 같은 친절한(?) 오류를 띄울 것입니다.
let x: u32;
let y = x + 1;
컴파일 결과:
error[E0381]: used binding `x` isn't initialized
--> src/main.rs:3:9
|
2 | let x: u32;
| - binding declared here but left uninitialized
3 | let y = x + 1;
| ^ `x` used here but it isn't initialized
|
help: consider assigning a value
|
2 | let x: u32 = 0;
| +++
Exercise
The exercise for this section is located in 02_basic_calculator/02_variables
-
Rust 컴파일러의 속도를 조금이라도 높이기 위해서는 가능한 모든 힌트가 필요합니다. ↩