μ—΄κ±°ν˜•

enum ν‚€μ›Œλ“œλŠ” λͺ‡κ°€μ§€ λ³€ν˜•(variant)으둜 ν‘œν˜„λ˜λŠ” μ—΄κ±°ν˜• νƒ€μž…μ„ μƒμ„±ν•©λ‹ˆλ‹€:

#[derive(Debug)]
enum Direction {
    Left,
    Right,
}

#[derive(Debug)]
enum PlayerMove {
    Pass,                        // λ‹¨μˆœ λ³€ν˜•
    Run(Direction),              // νŠœν”Œ λ³€ν˜•
    Teleport { x: u32, y: u32 }, // ꡬ쑰체 λ³€ν˜•
}

fn main() {
    let m: PlayerMove = PlayerMove::Run(Direction::Left);
    println!("이번 μ°¨λ‘€: {:?}", m);
}
This slide should take about 5 minutes.

ν‚€ 포인트:

  • Enumerations allow you to collect a set of values under one type.
  • Direction은 λ³€ν˜•μ„ κ°€μ§€λŠ” μ—΄κ±°ν˜• νƒ€μž…μž…λ‹ˆλ‹€. μ—¬κΈ°μ—λŠ” Direction::Left와 Direction::Right의 두 값이 ν¬ν•¨λ©λ‹ˆλ‹€.
  • PlayerMove is a type with three variants. In addition to the payloads, Rust will store a discriminant so that it knows at runtime which variant is in a PlayerMove value.
  • This might be a good time to compare structs and enums:
    • In both, you can have a simple version without fields (unit struct) or one with different types of fields (variant payloads).
    • You could even implement the different variants of an enum with separate structs but then they wouldn’t be the same type as they would if they were all defined in an enum.
  • RustλŠ” νŒλ³„μ‹μ„ μ €μž₯ν•˜λŠ” 데 μ΅œμ†Œν•œμ˜ 곡간을 μ‚¬μš©ν•©λ‹ˆλ‹€.
    • ν•„μš”ν•œ 경우 ν•„μš”ν•œ κ°€μž₯ μž‘μ€ 크기의 μ •μˆ˜λ₯Ό μ €μž₯ν•©λ‹ˆλ‹€.

    • ν—ˆμš©λœ λ³€ν˜• 값이 λͺ¨λ“  λΉ„νŠΈ νŒ¨ν„΄μ„ ν¬ν•¨ν•˜μ§€ μ•ŠλŠ” 경우 잘λͺ»λœ λΉ„νŠΈ νŒ¨ν„΄μ„ μ‚¬μš©ν•˜μ—¬ νŒλ³„μ‹μ„ μΈμ½”λ”©ν•©λ‹ˆλ‹€(β€˜ν‹ˆμƒˆ μ΅œμ ν™”β€™). 예λ₯Ό λ“€μ–΄ Option<&u8>은 μ •μˆ˜λ₯Ό κ°€λ¦¬ν‚€λŠ” ν¬μΈν„°λ‚˜ None λ³€ν˜•μ˜ 경우 NULL을 μ €μž₯ν•©λ‹ˆλ‹€.

    • Cμ™€μ˜ 연동을 μœ„ν•΄ μ‹λ³„μž 값을 직접 μ§€μ •ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€:

      #[repr(u32)]
      enum Bar {
          A, // 0
          B = 10000,
          C, // 10001
      }
      
      fn main() {
          println!("A: {}", Bar::A as u32);
          println!("B: {}", Bar::B as u32);
          println!("C: {}", Bar::C as u32);
      }

      repr 속성이 μ—†λ‹€λ©΄ 10001이 2 λ°”μ΄νŠΈλ‘œ ν‘œν˜„κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ— μ‹λ³„μžμ˜ νƒ€μž… ν¬κΈ°λŠ” 2 λ°”μ΄νŠΈκ°€ λ©λ‹ˆλ‹€.

더 μ‚΄νŽ΄λ³΄κΈ°

Rustμ—λŠ” enum이 더 적은 곡간을 μ°¨μ§€ν•˜λ„λ‘ ν•˜λŠ” 데 μ‚¬μš©ν•  수 μžˆλŠ” μ—¬λŸ¬ μ΅œμ ν™”κ°€ μžˆμŠ΅λ‹ˆλ‹€.

  • 널포인터 μ΅œμ ν™”: μ–΄λ–€ νƒ€μž…λ“€μ— λŒ€ν•΄μ„œ λŸ¬μŠ€νŠΈλŠ” size_of::<T>()κ°€ size_of::<Option<T>>()와 같은 것을 보μž₯ν•©λ‹ˆλ‹€.

    μ‹€μ œλ‘œ 널포인터 μ΅œμ ν™”κ°€ 적용된 것을 ν™•μΈν•˜κ³  μ‹Άλ‹€λ©΄ μ•„λž˜μ˜ μ˜ˆμ œμ½”λ“œλ₯Ό μ‚¬μš©ν•˜μ„Έμš”. μ£Όμ˜ν•  점은, μ—¬κΈ°μ—μ„œ λ³΄μ—¬μ£ΌλŠ” λΉ„νŠΈ νŒ¨ν„΄μ΄ μ»΄νŒŒμΌλŸ¬κ°€ 보μž₯ν•΄ μ£ΌλŠ” 것은 μ•„λ‹ˆλΌλŠ” μ μž…λ‹ˆλ‹€. 여기에 μ˜μ‘΄ν•˜λŠ” 것은 μ™„μ „νžˆ unsafeν•©λ‹ˆλ‹€.

    use std::mem::transmute;
    
    macro_rules! dbg_bits {
        ($e:expr, $bit_type:ty) => {
            println!("- {}: {:#x}", stringify!($e), transmute::<_, $bit_type>($e));
        };
    }
    
    fn main() {
        unsafe {
            println!("bool:");
            dbg_bits!(false, u8);
            dbg_bits!(true, u8);
    
            println!("Option<bool>:");
            dbg_bits!(None::<bool>, u8);
            dbg_bits!(Some(false), u8);
            dbg_bits!(Some(true), u8);
    
            println!("Option<Option<bool>>:");
            dbg_bits!(Some(Some(false)), u8);
            dbg_bits!(Some(Some(true)), u8);
            dbg_bits!(Some(None::<bool>), u8);
            dbg_bits!(None::<Option<bool>>, u8);
    
            println!("Option<&i32>:");
            dbg_bits!(None::<&i32>, usize);
            dbg_bits!(Some(&0i32), usize);
        }
    }