320x100
320x100

패턴 (pattern)

복잡하거나 단순한 타입의 구조와 매칭을 위한 러스트의 특수 문법

패턴을 match 표현 및 기타 구문과 함께 사용하면 프로그램 흐름을 더 잘 제어할 수 있음

패턴을 이용하기 위해서는 그 패턴을 어떤 값에 비교하는데, 패턴이 값에 매칭되면 코드에서 값 부분을 사용함

 

- 패턴의 구성

리터럴 값

해체한(destructured) 배열, 열거형, 구조체, 튜플

변수

와일드카드

자리표시자

 

 

 

 

match 갈래

// match VALUE {
//    PATTERN => EXPRESSION,
//    PATTERN => EXPRESSION,
// }

match x {
    None => None,
    Some(i) => Some(i + 1),
}

 

패턴은 match 표현식에서 갈래로 사용됨

match 표현식의 한 가지 요건은 match 표현식의 값에 대한 모든 경우의 수를 고려해야 한다는 의미에서 철저해야(exhaustive) 한다는 것임

모든 가능성을 포괄하는 것을 보장하는 방법 중 한 가지는 마지막 갈래에 포괄패턴(_)을 사용하는 것임

 

 

 

 

if let 조건 표현식

match를 짧게 작성하는 방법으로 if let, else if, else if let 표현식을 섞어서 매칭할 수 있음

패턴과 비교할 값을 하나만 표현할 수 있는 match 표현식 보다 더 유연하게 사용할 수 있음

그리고 러스트에서는 각 갈래들의 조건식이 서로 연관될 필요도 없음

 

 

 

 

while let 조건 루프

if let 구조와 비슷한 while let 조건 루프는 패턴이 계속 매칭되는 동안 while 루프를 실행할 수 있게 해줌

 

 

 

for 루프

for 루프에서 바로 뒤에 오는 것은 패턴임 (for x in y에서 x가 패턴)

 

 

 

let 구문

// let PATTERN = EXPRESSION;
let x = 5;

let (x, y, z) = (1, 2, 3);

 

let 구문 또한 패턴을 사용하는 것임

let x = 5는 이 패턴에 매칭되는 값을 변수 x에 대입하라는 의미임

 

 

 

 

함수 매개변수

fn foo(x: i32) {
    // do somthing
}

 

함수 매개변수도 패턴임

 

 

 

 

반박 가능성

패턴에는 반박 가능한 패턴과 반박 불가능한 패턴이 있음

 

- 반박 불가능한 패턴 (irrefutable)

반박 불가능한 패턴은 넘겨진 모든 가능한 값에 대해 매칭되는 패턴임

일례로 let x = 5; 구문에서 x는 무엇이든 매칭되므로 매칭에 실패할 수 없음

 

- 반박 가능한 패턴 (refutable)

이와 반대로 일부 가능한 값에 대해 매칭에 실패할 수 있는 패턴은 반박 가능한 패턴임

Some(x) 표현식에서 x가 None이면 패턴 매칭이 되지 않음

 

함수 매개변수, let 구문 및 for 루프에는 반박 불가능한 패턴만 허용될 수 있는데,

이는 매칭되지 않으면 프로그램이 의미있는 작업을 수행할 수 없기 때문

if let과 while let 표현식은 반박 가능한 패턴과 반박 불가능한 패턴을 허용하지만

컴파일러는 반박 불가능한 패턴에 대해 경고를 줌 (이 표현식들이 잠재적인 실패를 처리할 목적으로 만들어졌기 때문)

 

 

 

 

패턴 문법

리터럴 매칭

let x = 1;

match x {
    1 => println!("one"),
    2 => println!("two"),
    3 => println!("three"),
    _ => println!("anthing"),
}

 

 

명명된 변수매칭

명명된 변수는 어떤 값과도 매칭되는 반박 불가능한 패턴

fn main() {
    let x = Some(5);
    let y = 10;
    
    match x {
        Some(50) => println!("got 50"),
        Some(y) => println!("match y {y}"),
        _ => println!("default {:?}", x),
    }
    
    println!("end x = {:?}, y = {:?}", x, y);
}

 

 

다중 패턴

match 표현식에서는 패턴에 대한 또는(or) 연산자인 | 문법을 사용하여 여러 패턴을 매칭시킬 수 있음

fn main() {
    let x = 1;

    match x {
        1 | 2 => println!("one or two"),
        3 => println!("three"),
        _ => println!("anthing"),
    }
}

// result
// one or two

 

 

..=을 이용한 값의 범위 매칭

..= 문법은 경계 값을 포함하는 범위와 매칭시켜줌

fn main() {
    let x= 5;
    
    match x {
        1..=5 => println!("one through five"), // 1, 2, 3, 4, 5 중 하나에 매칭
        _ => println!("something else"),
    }
}

 

 

 

 

 

값을 해체하여 분리하기

구조체 분리하기

struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p = Point { x: 0, y: 7 };
    
    let Point { x: a, y: b } = p;
    
    assert_eq!(0, a); // true
    assert_eq!(7, b); // true
}
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p = Point { x: 0, y: 7 };
    
    match p {
        Point { x, y: 0 } => println!("x = {x}"),
        Point { x: 0, y } => println!("y = {y}"), // true
        Point { x, y } => println!("x = {x}, y = {y}"),
    }
}

 

 

열거형 해체하기

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

fn main() {
    let msg = Message::ChangeColor(0, 160, 255);
    
    match msg {
        Message::ChangeColor(r, g, b) => println!("red {r}, green {g}, blue {b}"),
    }
}

 

 

중첩된 구조체와 열거형 해체하기

enum Color {
    Rgb(i32, i32, i32),
    Hsv(i32, i32, i32),
}

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

fn main() {
    let msg = Message::ChangeColor(Color::Hsv(0, 160, 255));
    
    match msg {
        Message::ChangeColor(Color::Hsv(h, s, v)) => {
            println!("hue {h}, saturation {s}, value {v}")
        }
        _ => (),
    }
}

 

 

구조체와 튜플 해체하기

let ((feet, inches), Point { x, y }) = ((3, 10), Point { x: 3, y: -10 });

 

 

 

 

 

패턴에서 값 무시하기

패턴에서 값의 전체 또는 일부를 무사히는 방법은 여러가지가 있음

 

- _ 패턴 사용하기

- 다른 패턴 내에서 _ 패턴 사용하기

- 밑줄로 시작하는 이름 사용하기

- ..을 사용하여 값의 나머지 부분을 무시하기

 

 

_로 전체 무시하기

fn foo(_: i32, y: i32) {
    println!("only y {}", y);
}

fn main() {
    foo(3, 4);
}

 

 

중첩된 _로 값의 일부 무시하기

fn main() {
    let mut setting_value = Some(5);
    let new_setting_value = Some(10);

    match (setting_value, new_setting_value) {
        (Some(_), Some(_)) => {
            println!("can't overwrite customize value"); // true
        }
        _ => {
            setting_value = new_setting_value;
        }
    }
    
    println!("setting is {:?}", setting_value); // setting is Some(5)
}
fn main() {
    let numbers = (2, 4, 8, 16, 32);
    
    match numbers {
        (first, _, third, _, fifth) => {
            println!("{first}, {third}, {fifth}");
        }
    }
}

 

 

_로 시작하는 이름으로 사용하지 않는 변수 무시하기

fn main() {
    let _x = 5;
    let y = 10;
}

 

 

..으로 값의 나머지 부분 무시하기

struct Point {
    x: i32,
    y: i32,
    z: i32,
}

fn main() {
    let origin = Point { x: 0, y: 0, z: 0 };
    
    match origin {
        Point {x, .. } => println!("x is {}", x),
    }
}
fn main() {
    let numbers = (2, 4, 8, 16, 32);
    
    match numbers {
        (first, .., last) => {
            println!("{first}, {last}");
        }
    }
}

 

 

 

 

 

매치 카드를 사용한 추가 조건

매치 가드(match guard)는 match 갈래의 패턴 뒤에 지정되는 추가 if 조건으로, 해당 갈래가 선택되려면 이 조건도 매칭되어야함

매치 가드는 패턴만 가지고는 할 수 없는 더 복잡한 아이디어를 표현할 때 유용

fn main() {
    let Some(4);
    
    match num {
        Some(x) if x % 2 === 0 => println!("number is even {}", x), // true
        Some(x) => println!("number is odd"),
        None => (),
    }
}
fn main() {
    let x = Some(5);
    let y = 10;
    
    match x {
        Some(n) if n == y => println!("Matched n = {}", n),
        _ => println!("Default case x = {:?}", x), // true. n은 섀도잉 y는 외부변수
    }
}
fn main() {
    let x = 4;
    let y = false;
    
    match x {
        4 | 5 | 6 if y => println!("yes"), // true. 4 | 5 | (6 if y)
        _ => println!("no"),
    }
}

 

 

 

 

@ 바인딩

at 연산자 @을 사용하면 값에 대한 패턴 매칭 여부를 테스트하는 동시에 해당 값을 갖는 변수를 만들 수 있음

enum Message {
    Hello { id: i32 },
}

fn main() {
    let msg = Message::Hello { id: 5 };
    
    match msg {
        Message::Hello {
            id: id_variable @ 3..7,
        } => println!("Found am id in range {}", id_variable), // true. id_variable에 @을 지정하여 3~7 범위에 매칭되는 어떤 값이든 캡처
        Message::Hello { id: 10..=12 } => {
            println!("Found an id in another range")
        }
        Message::Hello { id } => println!("Found same id: {}", id),
    }
}

 

300x250
728x90

'Programming > Rust' 카테고리의 다른 글

러스트 고급 트레이트  (0) 2025.10.12
안전하지 않은 러스트  (0) 2025.10.12
러스트의 객체 지향 프로그래밍 기능  (0) 2025.10.11
러스트 동시성  (0) 2025.10.09
러스트 스마트 포인터  (0) 2025.10.09