패턴은 러스트가 간단한 타입과 복잡한 타입의 구조 모두를 매칭할 수 있는 특별한 문법이다. 패턴을 match 표현식과 더불어 다른 구조와 함께 사용하면 프로그램의 흐름을 더욱 세밀하게 제어할 수 있다. 패턴은 아래와 같은 요소들의 조합으로 구성된다.

  • 리터럴
  • 해체된 배열, 열거자, 구조체/튜플
  • 변수
  • 와일드카드
  • placeholder

패턴을 사용할 수 있는 위치

  • match 표현식의 arms
    match VALUE
      PATTERN => EXPRESSION,
      PATTERN => EXPRESSION,
      PATTERN => EXPRESSION,
    }
    
  • if let 조건 표현식
    • else if, else if let 표현식을 조합해서 match 표현식보다 더 유연한 코드를 사용할 수 있다.
    • 단점은 match표현식과 달리 모든 경우를 고려하고 있는지 컴파일러가 검사하지 않는다는 점이다.
  • while let 조건 루프
    let mut stack = Vec::new();
    
    stack.push(1);
    stack.push(2);
    stack.push(3);
    
    while let Some(top) = stack.pop() {
        println!("{}", top);
    }
    
  • for 루프
    let v = vec!['a', 'b', 'c'];
    
    for (index, value) in v.iter().enumerate() {
        println!("{} is at index {}", value, index);
    }
    
  • let 구문
    • let x = 5;
    • 일반적인 let 구문이라 알아차리지 못했었을지라도 패턴을 이용하는 것이다.
    • let PATTERN = EXPRESSION
    • 즉 변수의 이름은 가장 간단한 형태의 패턴인 것이다.
  • 함수 매개변수
    • 함수의 매개변수에도 패턴을 이용할 수 있다. 아래 코드의 foo함수는 i32 타입의 매개변수 x를 정의한다.
      fn foo(x: i32) {
        // code goes here
      }
      

refutable / irrefutable pattern

  • 패턴은 부인할 수 있는(refutable) 패턴과 부인할 수 없는(irrefutable) 패턴으로 나뉜다.
  • let x = 5 에서 x는 refutable pattern이다. x는 모든 값에 일치하므로 패턴 비교가 실패할 수 없기 때문이다.
  • if let Some(x) = a_value 에서 Some(x)는 irrefutable 패턴이다. a_value의 값이 None이면 Some(x)와 일치하지 않기 때문이다.
  • 일반적으로 refutable / irrefutable pattern을 구분할 필요는 없다. 하지만 부인 가능성(refutability)의 개념을 이해해야 에러메시지에 적절히 대응할 수 있다. 에러가 발생하면 코드의 동작에 따라 패턴이나 패턴을 구성하는 코드를 수정해야 한다.