320x100
320x100

열거형 (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 {}

 

300x250
728x90