열거형 (enumeration, enum)
러스트에서는 하나의 타입이 가질 수 있는 variant를 열거하여 타입을 정의할 수 있도록 해줌
여러 값이 여러 개의 가능한 값의 집합 중 하나라는 것을 나타내는 방법을 제공
구조체를 사용할 때보다 간결하게 동일한 개념을 표현할 수 있음
열거형은 각 variant가 다른 타입과 다른 크기의 값을 가질 수 있어 구조체로는 불가능한 구현이 가능
// IP 주소의 배리언트를 커스텀 데이터 타입으로 정의
enum IpAddr {
V4(u8, u8, u8, u8), // 인수를 입력받아서 IpAddr 타입의 인스턴스를 만드는 함수 (생성자)
V6(String),
}
fn main() {
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
}
Option 열거형
Option 타입은 값이 있거나 없을 수 있는 상황을 표현
러스트에는 null 개념이 없기 때문에 다른 언어에는 존재하는 null 값을 null 값이 아닌 것 처럼 사용하는 등으로 인해 발생하는 null로 인한 문제가 발생하지 않는다
대신 값의 존재 혹은 부재를 표현하는 열거형인 Option<T>라는 타입이 있어 null을 대체함
Options<T>인 변수에 대한 연산은 Options<T>인 변수끼리만 가능 (null이 가능함을 명시함으로써 null로 인해 발생하는 문제인 실제 nulld인데 null이 아니라고 가정하는 상황을 방지)
// 표준 라이브러리에 정의된 Option<T>
enum Option<T> {
None,
Some(T),
}
fn main() {
let some_number = Some(5);
let some_char = Some('e');
let absent_number: Option<i32> = None;
}
match 제어 흐름 구조
일련의 패턴에 대해 어떤 값을 비교한 뒤 어떤 패턴에 매칭되었는지를 바탕으로 코드를 수행하도록 해줌
패턴은 리터럴 값, 변수명, 와일드카드 등 다양한 것으로 구성될 수 있음
일반적으로 Option<T> 값을 사용하기 위해서는 각 variant를 처리할 코드가 필요
Some(T) 값 일 떄만 실행되어서 내부의 T 값을 사용하는 코드도 필요하고 None 값일때만 실행될 코드도 필요하다
match 표현식은 열거형과 함께 사용할 때 이런 작업을 수행하는 제어 흐름 구조로 열거형의 variant에 따라 다른 코드를 실행하고 매칭되는 값 내부의 데이터를 해당 코드에서 사용할 수 있게 해줌
enum UsState {
Alabama,
Alaska,
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
// Coin::Quarter와 매칭되는 패턴에 state라는 이름의 변수를 추가
Coin::Quarter(state) => {
println!("State quarter fron {::?}!", state);
}
}
}
fn main() {
let result = value_in_cents(Coin::Quarter(UsState::Alaska));
}
Option<T>를 이용하는 매칭
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
None => None,
Some(i) => Some(i + 1),
}
}
fn main() {
let five = Some(5);
let six = plus_one(five); // None => None를 넘어 다음 갈래에서 연산
let none = plus_one(None);
}
포괄 패턴
열거형을 사용하면서 몇 개 값에 대해서는 특별한 동작을 하지만 그 외의 값들에 대해서 기본 동작을 취하도록 할 수 있음
let dice_roll = 9;
match dice_roll {
3 => add(),
7 => remove(),
_ => (), // 포괄 값. 어떠한 값이라도 매칭이 되지만 그 값을 바인딩하지 않겠다는 의미
}
fn add() {}
fn remove () {}
if let을 사용한 간결한 제어 흐름
if let 문법은 if와 let을 조합하여 하나의 패턴만 매칭시키고 나머지 경우는 무시하도록 값을 처리하는 간결한 방법을 제공
match 보다 보일러플레이트 코드를 덜 쓰지만 match가 강제했던 철저한 검사를 하지 않게 됨
if let은 한 패턴에 매칭될 때만 코드를 실행하고 다른 경우는 무시하는 match 문을 작성할 때 사용하는 syntax sugar임
let config_max = Some(3u8);
match config_max {
Some(max) => println!("maximum: {}", max),
_ => (),
}
// 위 match와 동일
if let Some(max) = config_max {
println!("maximum: {}", max);
} else {}
'Programming > Rust' 카테고리의 다른 글
| 러스트 컬렉션 (collection) (1) | 2025.09.02 |
|---|---|
| 러스트 프로젝트 관리 (패키지, 크레이트, 모듈) (4) | 2025.09.01 |
| 러스트의 구조체에 대해 알아보자 (3) | 2025.08.18 |
| 러스트 소유권 이해하기 (7) | 2025.08.13 |
| 러스트의 일반적인 프로그래밍 개념 (6) | 2025.08.12 |
