Using Match with Enum



match 는 다른 언어의 switch 와 비슷함. 대상을 지정해놓고 대상의 값이 될 수 있는 목록을 나열하고 매칭되는 값에 해당하는 코드를 실행함. 그 대상은 리리터럴, 변수, 와일드카드 등 여러가지가 될 수 있는데, 여기서는 enum 과 함께 사용하는 법을 다룸.


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,
}
}


위의 match 는 value_in_cents 의 파라미터로 넘겨받은 enum 에 매칭되는 값을 값을 반환함. if 와 비슷하지만, if 의 조건절에는 Boolean 값만이 올 수 있지만 match 에는 어떠한 타입도 사용 가능하다는 차이가 있음.


문법적으로, match 에 나열된 비교 대상을 패턴이라 칭함. 비교는 작성된 순서(위에서 아래)로 이루어지며, 패턴 매칭이 발생하면 나머지 패턴 비교는 수행하지 않음. 


위의 Penny 에서 처럼, 실행될 코드가 두 줄 이상이면 중괄호를 써서 줄을 나눔.


match 는 철저함. enum 타입으로 비교할 때, 이 타입의 모든 패턴을 다루어야 함. 해당 타입에 빼놓은 패턴이 있다면 이는 컴파일 에러를 일으킴. 아래는 그 예:


enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}

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

}
}

이처럼 match 로 Coin 타입을 다루면서 Quarter 를 빼놓으면 컴파일 에러!



플레이스홀더 _


match 는 편의상 플레이스홀더를 제공함. 이는 다른 언어의 switch 에 있는 default 라 보면 됨. 패턴 비교를 하다가 '여기부턴 나머지 모두 똑같이' 를 구현하고 싶을 때 사용. 패턴에 '_' 를 사용하면 됨.


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


1 - 3 - 5 - 7 까지 비교하여 매칭되지 않으면 모두 () 를 반환.



값을 지닌 enum 패턴


enum 은 안에 자신의 값을 가질 수 있다고 했음. 아래 코드는 이 값이 match 와 어떤식으로 사용될 수 있는지 보여줌.


enum UsState {
Alabama,
Alaska,
}

enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}

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


Coin::Quarter 패턴에서 보듯, enum 의 값을 실행 코드에서 사용할 수 있음. Coin::Quarter 가 파라미터로 주어지면, 각 패턴을 위에서부터 순서대로 비교하다가 Quarter 에서 매칭이 발생하고, Quarter 의 값, UsState 가 패턴 안의 state 에 바인딩 되고, 이 state 를 매칭 코드에서 사용할 수 있게 됨.



Option<T>


이전에 다룬 Option<T> 에서 Some 값을 사용할 수 있음. 


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);


Coin::Quarter 에서와 같음. plus_one 함수에서 Some 값이 i 에 바인딩되어 + 1 한 값이 반환됨. 물론 값 그대로가 아닌, Some(i + 1) 의 형태로. None 의 경우 None 이 반환됨. None 도 Option<T> 타입이기 때문에 반환될 수 있음.







'Rust' 카테고리의 다른 글

모듈  (0) 2018.02.22
Enum(if let)  (0) 2018.02.21
Enum(Option<T>)  (0) 2018.02.21
Enum  (0) 2018.02.21
구조체(메서드)  (0) 2018.02.20

+ Recent posts