Rust - chapter 6(열거형)


공식 문서 - 번역글의 6번째 챕터 정리

대부분의 언어에서 열거형을 지원하고 있고 유사하지만 세부적으로 다른 부분이 있다. Rust 의 열거형은 함수형 언어(Haskell, OCaml, …)의 대수 데이터 타입과 비슷하다고 한다. (위 언어들을 만져본 적이 없어서 정확히 모르겠다.. 공부필요 💦)

Enums - 열거형

번역글에서는 열거형에 대해 이렇게 정의하고 있다.

💿   IP 주소를 다뤄야 하는 경우를 생각해 봅시다. 현재 IP 주소에는 두 개의 주요한 표준이 있습니다: 버전 4와 버전 6입니다. 프로그램에서 다룰 IP 주소의 경우의 수는 이 두 가지가 전부입니다: 모든 가능한 값들을 나열(enumerate) 할 수 있으며, 이 경우를 열거라고 부를 수 있습니다. 열거형의 값은 variants 중 하나만 될 수 있습니다.

아래와 같은 경우 IpAddrKind 이라는 열거형을 정의하면서 포함할 수 있는 IP 주소인 V4V6 를 나열하여 이 개념을 코드에 표현할 수 있습니다. V4V6 를 열거형의 variants 라고 하고 IpAddrKind::V4IpAddrKind::V6 와 같이 :: 을 이용하여 사용 할 수 있다.
각 Variants 는 자료형을 가질수 있으며 가지지 않을 경우는 이름이 타입으로 사용된다.

enum IpAddrKind {
    V4,
    V6,
}

fn route(ip_type: IpAddrKind) { }

route(IpAddrKind::V4);
route(IpAddrKind::V6);

또한 각 variant 는 아래와 같이 각기 다른 타입과 개수를 가질 수 있다.

enum IpAddr {
    V4(u8, u8, u8, u8),
    V6(String),
}

let home = IpAddr::V4(127, 0, 0, 1);

let loopback = IpAddr::V6(String::from("::1"));

또한 IpAddr 와 같은 IP 주소의 경우는 사용하는 경우가 많기 때문에 이미 표준라이브러리에 등록이 되어 있으며 표준 라이브러리에서는 아래와 같이 정의하고 있다.

struct Ipv4Addr {
    // details elided
}

struct Ipv6Addr {
    // details elided
}

enum IpAddr {
    V4(Ipv4Addr),
    V6(Ipv6Addr),
}

열거형은 그룹화에 의미가 있으며, impl 을 통해서 메소드 정의가 가능하다.

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

impl Message {
    fn call(&self) {
        // 메소드 내용은 여기 정의할 수 있습니다.
    }
}

let m = Message::Write(String::from("hello"));
m.call();

Option

Option 은 표준라이브러리에 있는 열거형이다. 해당 열거형은 값이 있거나 없거나 하는 상황을 나타낼 때 사용할 수 있는 열거형이다.

💿   Rust 는 null 이 없다.

러스트에서는 null 이 없지만 값의 존재, 부재의 개념으로 Option<T> 열거형을 사용할 수 있다. Option 을 붙이지 않고 Some, None 으로 사용할 수 있다.
Some 의 경우는 들어오는 인자를 통해 타입을 알 수 있지만 None 을 사용할 경우는 꼭 타입을 명시해줘야 한다.
당연한 이야기이라고 생각하실 수도 있지만 Option<T>T 는 다르다. 따라서 일반적으로 연산을 할 수도 없다.

enum Option<T> {
    Some(T),
    None,
}

let some_number = Some(5);
let some_string = Some("a string");

let absent_number: Option<i32> = None;

match 연산자

흐름 제어 연산자 이다. JSswitch 문과 비슷하다. Option<T> 을 사용할 수 있다.

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn value_in_cents(coin: Coin) -> u32 {
    match coin {
        Coin::Penny => {
            println!("Lucky penny!");
            1
        },
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}

let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);

_변경자

js 에서의 switchdefault 와 비슷하다.

let some_u8_value = 0u8;
match some_u8_value {
    1 => println!("one"),
    3 => println!("three"),
    5 => println!("five"),
    7 => println!("seven"),
    _ => (),
}

if let

대부분의 언어가 가지고 있는 if 문이라고 볼 수 있겠다. 라고 생각했는데 if 문이 따로 존재한다.
다른 용도를 가지고 있는 것 같은데 아직 명확히 이해하지 못 하였다..

if let Some(3) = some_u8_value {
    println!("three");
}

개인이 참고하고자 작성한 글이며, 잘못된 정보가 있을 수 있습니다. 잘못된 정보는 메일로 보내주시면 감사하겠습니다. 🙏

Tags: ,

Categories:

Updated: