본문 바로가기

패턴이 사용될 수 있는 모든 곳

match·if let·while let·for·let·함수 매개변수에서 패턴이 값을 해체하고 바인딩하는 방식을 한 흐름으로 익힙니다.

패턴(pattern)은 단순한 타입이든 복잡한 타입이든 타입의 구조에 맞춰 매칭하는 러스트의 특별한 문법입니다. 패턴을 match 표현식이나 다른 구문과 함께 쓰면 프로그램의 제어 흐름을 더 잘 다룰 수 있습니다. 패턴은 다음을 조합해 이루어집니다.

패턴을 이루는 것
리터럴
배열, 열거형, 구조체, 튜플의 해체
변수
와일드카드
자리 표시자

x, (a, 3), Some(Color::Red)가 패턴의 예입니다. 패턴이 올바른 맥락에서는, 이런 구성 요소가 데이터의 모양을 나타냅니다. 그러면 프로그램은 값을 패턴과 맞춰 보며, 특정 코드를 계속 실행하기에 알맞은 모양의 데이터인지 판단합니다.

패턴을 쓰려면 값과 비교합니다. 패턴이 값과 맞으면, 코드에서 그 값의 부분들을 씁니다. match 제어 흐름 구조에서 동전 분류기 예제처럼 패턴을 쓰는 match 표현식을 떠올려 보세요. 값이 패턴의 모양에 맞으면 이름 붙은 조각들을 쓸 수 있습니다. 맞지 않으면 그 패턴에 연결된 코드는 실행되지 않습니다.

이번 장은 패턴과 관련된 모든 것을 정리한 참고 자료입니다. 패턴을 쓸 수 있는 곳, 반박 가능한 패턴과 반박 불가능한 패턴의 차이, 그리고 보게 될 여러 종류의 패턴 문법을 다룹니다. 이 장을 마치면 패턴으로 많은 개념을 분명하게 나타내는 방법을 알게 됩니다.

패턴이 사용될 수 있는 모든 곳

패턴은 러스트의 여러 곳에서 나타나며, 그런 줄 모르고 이미 많이 써 왔습니다. 이 절에서는 패턴이 유효한 모든 곳을 이야기합니다. 아래 그림은 같은 패턴이 놓이는 구문에 따라 무엇을 요구하고, 맞지 않을 때 어떻게 흘러가는지를 한눈에 정리한 것입니다.

RUST · 패턴과 코드

패턴은 값을 해체하고, 구문은 불일치를 처리한다

동일한 패턴도 놓이는 구문에 따라 성공해야 하는 조건과 실패했을 때의 흐름이 달라집니다.

match · 가능한 모든 경우 처리

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

각 갈래는 실패할 수 있어도, 가드 없는 갈래 집합이 모든 가능한 값을 덮어야 합니다.

if let · 일치하면 분기

if let Some(color) = favorite_color {
    // color 사용
}

불일치하면 본문을 건너뛰거나 else를 실행합니다. 전체 경우를 처리했는지 검사하지 않습니다.

while let · 일치하는 동안 반복

while let Some(top) = stack.pop() {
    println!("{top}");
}

매번 pop을 실행하고 Some이면 바인딩·본문, None이면 종료합니다.

for · 각 항목 해체

for (index, value)
    in v.iter().enumerate()
{
    // 튜플 항목을 두 이름으로 해체
}

항목 타입의 모든 값에 맞는 반박 불가능 패턴이어야 합니다.

let · 값 바인딩

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

단순 let은 반박 불가능 패턴을 요구합니다. 이 튜플에서 x=1, y=2, z=3입니다.

함수·클로저 매개변수 · 인자 해체

fn point(&(x, y): &(i32, i32)) {
    // x와 y는 각각 i32
}

매개변수도 반박 불가능 패턴입니다. 본문의 &(3,5)를 받으면 x=3, y=5입니다.

let-else · 실패하면 현재 흐름에서 벗어난다

let Some(x) = value else { return };

반박 가능 패턴을 허용하며 else는 return·break·panic!처럼 발산해야 합니다. 성공한 x는 이후 구문에서도 사용합니다.

코드는 각 문맥의 핵심 발췌입니다. 패턴의 허용 조건과 실행 흐름을 구분하면 구문을 목적에 맞게 선택할 수 있습니다.

match의 각 갈래는 실패할 수 있지만, 가드가 없는 갈래들이 모여 가능한 모든 값을 덮어야 합니다. if let은 맞으면 본문을, 맞지 않으면 본문을 건너뛰거나 else를 실행하며, 모든 경우를 다루었는지 확인하지 않습니다. while let은 매번 pop을 실행해 Some이면 바인딩하고 본문을 실행하며, None이면 끝납니다. for의 패턴, 단순한 let, 함수와 클로저의 매개변수는 모든 값에 맞는 반박 불가능한(irrefutable) 패턴이어야 합니다. 그림의 let에서는 x=1, y=2, z=3이 되고, 매개변수 &(x, y)에 &(3, 5)를 넘기면 x=3, y=5가 됩니다. let...else는 반박 가능한 패턴을 허용하며, else는 return이나 break, panic!처럼 현재 흐름을 벗어나야 하고, 성공해 바인딩한 이름은 그 뒤의 구문에서도 쓸 수 있습니다. let...else는 if let을 사용한 간결한 제어 흐름에서 다루었습니다. 그림의 코드는 각 구문의 핵심만 뽑은 것이며, 이 글에서 하나씩 봅니다.

match 갈래

match 제어 흐름 구조에서 이야기했듯, match 표현식의 갈래에 패턴을 씁니다. 형식으로 보면, match 표현식은 match 키워드, 매칭할 값, 그리고 패턴과 그 패턴이 값과 맞을 때 실행할 표현식으로 이루어진 하나 이상의 갈래로 정의됩니다.

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

예를 들어 다음은 변수 x의 Option<i32> 값에 매칭하는 match 표현식입니다. x가 None이면 첫 갈래가, Some이면 둘째 갈래가 맞으며, 둘째 갈래는 안의 값을 i에 묶어 1을 더한 Some을 만듭니다.

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

이 match 표현식의 패턴은 각 화살표 왼쪽의 None과 Some(i)입니다.

match 표현식에는 철저해야(exhaustive) 한다는 요구 사항이 있습니다. match 표현식의 값에 대한 모든 가능성을 다루어야 한다는 뜻입니다. 모든 가능성을 다루었는지 확실히 하는 한 방법은 마지막 갈래에 모든 것을 잡는 패턴을 두는 것입니다. 예를 들어 어떤 값에든 맞는 변수 이름은 결코 실패할 수 없으므로, 남은 모든 경우를 다룹니다.

특별한 패턴 _는 무엇이든 맞지만 변수에 바인딩하지 않으므로, 흔히 마지막 match 갈래에 씁니다. 예를 들어 지정하지 않은 값을 모두 무시하고 싶을 때 _ 패턴이 쓸모 있습니다. _ 패턴은 패턴에서 값 무시하기에서 더 자세히 다룹니다.

if let 조건 표현식

if let을 사용한 간결한 제어 흐름에서는 주로 if let 표현식을 한 경우만 매칭하는 match를 짧게 쓰는 방법으로 이야기했습니다. 선택적으로 if let에는, if let의 패턴이 맞지 않을 때 실행할 코드가 담긴 else를 둘 수 있습니다.

다음 코드는 if let, else if, else if let 표현식을 섞어 쓸 수도 있다는 것을 보여 줍니다. 이렇게 하면 패턴과 비교할 값 하나만 표현할 수 있는 match 표현식보다 유연해집니다. 또 러스트는 일련의 if let, else if, else if let 갈래의 조건들이 서로 관련되어 있기를 요구하지 않습니다.

이 코드는 여러 조건을 차례로 확인해 배경을 무슨 색으로 할지 정합니다. 이 예에서는 실제 프로그램이라면 사용자 입력으로 받을 값들을 하드코딩한 변수로 만들었습니다.

src/main.rs
fn main() {
    let favorite_color: Option<&str> = None;
    let is_tuesday = false;
    let age: Result<u8, _> = "34".parse();

    if let Some(color) = favorite_color {
        println!("Using your favorite color, {color}, as the background");
    } else if is_tuesday {
        println!("Tuesday is green day!");
    } else if let Ok(age) = age {
        if age > 30 {
            println!("Using purple as the background color");
        } else {
            println!("Using orange as the background color");
        }
    } else {
        println!("Using blue as the background color");
    }
}

사용자가 좋아하는 색을 지정했다면 그 색을 배경으로 씁니다. 좋아하는 색이 지정되지 않았고 오늘이 화요일이라면 배경은 초록색입니다. 그렇지 않고 사용자가 나이를 문자열로 지정했고 그것을 숫자로 파싱할 수 있다면, 숫자의 값에 따라 색은 보라색이나 주황색입니다. 이 조건 가운데 어느 것도 해당하지 않으면 배경은 파란색입니다.

이 조건 구조로 복잡한 요구 사항을 지원할 수 있습니다. 여기 있는 하드코딩한 값으로 이 예제는 Using purple as the background color를 출력합니다.

if let도 match 갈래처럼 기존 변수를 가리는 새 변수를 도입할 수 있습니다. if let Ok(age) = age 줄은 Ok 배리언트 안의 값을 담는 새 age 변수를 도입하며, 이 변수는 기존의 age 변수를 가립니다. 새 age는 if let의 본문 블록 안에서 쓸 수 있으므로, 이 코드는 if age > 30 조건을 그 블록 안에 둡니다. 2024 에디션의 let 체인으로 if let Ok(age) = age && age > 30처럼 두 조건을 합칠 수도 있으며, 이때 30과 비교하는 age는 && 앞의 패턴에서 새로 바인딩된 u8 값입니다. 다만 이렇게 합치면 나이가 30 이하일 때 이 조건이 거짓이 되어 마지막 else로 넘어가 파란색을 고르므로, 이 예제는 주황색 갈래를 두려고 비교를 블록 안에서 따로 합니다.

if let 표현식을 쓰는 단점은 컴파일러가 철저한지 확인하지 않는다는 것입니다. match 표현식에서는 확인합니다. 마지막 else 블록을 빼먹어 일부 경우를 다루지 않았다면, 컴파일러는 생길 수 있는 논리 버그를 알려 주지 않습니다.

while let 조건 루프

if let과 구조가 비슷한 while let 조건 루프는, 패턴이 계속 맞는 동안 while 루프를 실행하게 합니다. 다음 코드는 벡터를 스택처럼 써서, 넣은 순서의 반대로 벡터의 값을 출력하는 while let 루프입니다.

src/main.rs
fn main() {
    let mut stack = Vec::new();

    stack.push(1);
    stack.push(2);
    stack.push(3);

    while let Some(top) = stack.pop() {
        println!("{top}");
    }
}
3
2
1

이 예제는 3, 2, 1을 출력합니다. pop 메서드는 벡터의 마지막 원소를 꺼내 Some(value)로 돌려줍니다. 벡터가 비어 있으면 pop은 None을 돌려줍니다. while 루프는 pop이 Some을 돌려주는 동안 블록 안의 코드를 계속 실행합니다. pop이 None을 돌려주면 루프가 멈춥니다. while let으로 스택에서 모든 원소를 꺼낼 수 있습니다. 아래 그림은 이 루프의 흐름을 보여 줍니다.

while let 반복 제어 흐름

매 회차 stack pop→Some 바인딩/출력→다음 pop, 마지막 None 종료에서 실제 Vec와 현재 top이 바뀐다.

RUST · FLOWCHART

while let은 pop이 Some인 동안 실행하고 None에서 끝난다

while let은 패턴이 계속 맞는 동안만 바인딩과 본문 실행을 반복합니다.

while let 반복 제어 흐름 다음 값, 패턴 검사, 바인딩, 본문, 종료의 다섯 단계와 본문에서 다음 검사로 돌아가는 반복 화살표를 보여줍니다. 예 아니요 다시 검사 다음 값을 가져온다 stack.pop() → Option Some(pattern) 에 맞는가? 패턴 변수를 바인딩 성공 값만 이름에 연결 루프 본문 실행 본문 뒤 다음 값으로 불일치: 종료 None 또는 패턴 불일치
매 회차 pop을 다시 평가하며 Some만 바인딩·본문 실행 후 되돌아가고 None은 종료한다.pop→match: pop 결과를 패턴 검사。match→body: 일치한 경우만 top 바인딩。match→exit: 값이 없으면 종료。body→pop: 본문 다음에 다음 popSomeNonestack.pop()stack.pop()다음 값 평가Some인가?Some인가?패턴 검사top 바인딩top바인딩Some3 · 2 · 1값 출력NoneNone반복종료
단계별 조건과 보충 설명
  1. 다음 값

    Option을 만드는 다음 단계를 실행합니다.

  2. 패턴 검사

    Some(pattern)에 맞으면 변수를 바인딩하고, 맞지 않으면 루프를 종료합니다.

  3. 본문

    바인딩된 값을 사용해 본문을 실행합니다.

  4. 재검사

    본문 뒤 다음 값으로 돌아가 같은 검사를 반복합니다.

본문의 stack=[1,2,3] · 마지막 값부터 pop

1 · Some(3)

top=3을 바인딩하고 3 출력

2 · Some(2)

top=2를 바인딩하고 2 출력

3 · Some(1)

top=1을 바인딩하고 1 출력

다음 pop은 None입니다. 패턴이 맞지 않아 본문을 실행하지 않고 반복을 종료합니다.

  • 성공 반복
  • 불일치 종료

다음 값을 검사해 Some이면 바인딩·본문·재검사를 하고, 불일치하면 끝나는 while let 제어 흐름입니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
첫 pop·출력

stack=[1,2,3]의 마지막 원소 3을 꺼내 top으로 바인딩하고 출력한다.

  • 결과·top: Some(3) · 3
  • 남은 stack: [1,2]
  • 출력: 3
  • pop은 마지막 원소를 제거한다. Some(3)이 패턴과 맞으므로 top=3으로 본문을 실행한다.
후속 pop·출력

Some(2)와 Some(1)을 차례로 받아 출력하면 stack은 빈다.

  • 후속 결과: Some(2) → Some(1)
  • 누적 출력: 3, 2, 1
  • 남은 stack: []
  • while let은 매 회차 새 stack.pop()을 평가하므로 현재 마지막 원소 2, 1이 차례로 제거된다.
None 종료

빈 stack의 다음 pop은 None이므로 본문을 실행하지 않는다.

  • stack: []
  • 결과: None
  • 본문: 미실행 · 반복 종료
  • Some(top) 패턴이 None과 맞지 않아 반복을 끝낸다. None을 숫자처럼 출력하지 않는다.

while let 반복 제어 흐름

매 회차 stack pop→Some 바인딩/출력→다음 pop, 마지막 None 종료에서 실제 Vec와 현재 top이 바뀐다.

RUST · FLOWCHART

while let은 pop이 Some인 동안 실행하고 None에서 끝난다

while let은 패턴이 계속 맞는 동안만 바인딩과 본문 실행을 반복합니다.

while let 반복 제어 흐름 다음 값, 패턴 검사, 바인딩, 본문, 종료의 다섯 단계와 본문에서 다음 검사로 돌아가는 반복 화살표를 보여줍니다. 예 아니요 다시 검사 다음 값을 가져온다 stack.pop() → Option Some(pattern) 에 맞는가? 패턴 변수를 바인딩 성공 값만 이름에 연결 루프 본문 실행 본문 뒤 다음 값으로 불일치: 종료 None 또는 패턴 불일치
매 회차 pop을 다시 평가하며 Some만 바인딩·본문 실행 후 되돌아가고 None은 종료한다.pop→match: pop 결과를 패턴 검사。match→body: 일치한 경우만 top 바인딩。match→exit: 값이 없으면 종료。body→pop: 본문 다음에 다음 popSomeNonestack.pop()stack.pop()다음 값 평가Some인가?Some인가?패턴 검사top 바인딩top바인딩Some3 · 2 · 1값 출력NoneNone반복종료
단계별 조건과 보충 설명
  1. 다음 값

    Option을 만드는 다음 단계를 실행합니다.

  2. 패턴 검사

    Some(pattern)에 맞으면 변수를 바인딩하고, 맞지 않으면 루프를 종료합니다.

  3. 본문

    바인딩된 값을 사용해 본문을 실행합니다.

  4. 재검사

    본문 뒤 다음 값으로 돌아가 같은 검사를 반복합니다.

본문의 stack=[1,2,3] · 마지막 값부터 pop

1 · Some(3)

top=3을 바인딩하고 3 출력

2 · Some(2)

top=2를 바인딩하고 2 출력

3 · Some(1)

top=1을 바인딩하고 1 출력

다음 pop은 None입니다. 패턴이 맞지 않아 본문을 실행하지 않고 반복을 종료합니다.

  • 성공 반복
  • 불일치 종료

다음 값을 검사해 Some이면 바인딩·본문·재검사를 하고, 불일치하면 끝나는 while let 제어 흐름입니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
첫 pop·출력

stack=[1,2,3]의 마지막 원소 3을 꺼내 top으로 바인딩하고 출력한다.

  • 결과·top: Some(3) · 3
  • 남은 stack: [1,2]
  • 출력: 3
  • pop은 마지막 원소를 제거한다. Some(3)이 패턴과 맞으므로 top=3으로 본문을 실행한다.
후속 pop·출력

Some(2)와 Some(1)을 차례로 받아 출력하면 stack은 빈다.

  • 후속 결과: Some(2) → Some(1)
  • 누적 출력: 3, 2, 1
  • 남은 stack: []
  • while let은 매 회차 새 stack.pop()을 평가하므로 현재 마지막 원소 2, 1이 차례로 제거된다.
None 종료

빈 stack의 다음 pop은 None이므로 본문을 실행하지 않는다.

  • stack: []
  • 결과: None
  • 본문: 미실행 · 반복 종료
  • Some(top) 패턴이 None과 맞지 않아 반복을 끝낸다. None을 숫자처럼 출력하지 않는다.

매번 stack.pop()으로 다음 값을 평가해 Option을 얻고, Some(pattern)에 맞는지 확인합니다. 맞으면 성공한 값만 top에 바인딩하고 본문을 실행한 뒤, 다시 다음 값으로 돌아갑니다. stack=[1, 2, 3]에서는 마지막 값부터 Some(3), Some(2), Some(1)을 받아 3, 2, 1을 출력하고, 그다음 pop은 None이므로 패턴이 맞지 않아 본문을 실행하지 않고 루프를 끝냅니다.

for 루프

for 루프에서 for 키워드 바로 뒤에 오는 값이 패턴입니다. 예를 들어 for x in y에서 x가 패턴입니다. 다음 코드는 for 루프에서 패턴으로 튜플을 해체하거나 분리하는 방법을 보여 줍니다.

src/main.rs
fn main() {
    let v = vec!['a', 'b', 'c'];

    for (index, value) in v.iter().enumerate() {
        println!("{value} is at index {index}");
    }
}
a is at index 0
b is at index 1
c is at index 2

enumerate 메서드로 반복자를 바꿔, 값과 그 값의 인덱스를 튜플로 만들어 내게 합니다. 처음 만들어지는 값은 튜플 (0, 'a')입니다. 이 값이 패턴 (index, value)에 맞춰지면 index는 0, value는 'a'가 되어 출력의 첫 줄을 출력합니다.

let 구문

이번 장 전에는 match와 if let에서만 패턴을 쓴다고 명시적으로 이야기했지만, 사실 let 구문을 비롯한 다른 곳에서도 패턴을 써 왔습니다. 예를 들어 let으로 하는 다음의 간단한 변수 대입을 봅니다.

let x = 5;

이런 let 구문을 쓸 때마다 패턴을 써 온 것입니다. 깨닫지 못했을 수도 있습니다. 더 형식적으로 보면, let 구문은 다음과 같습니다.

let PATTERN = EXPRESSION;

let x = 5;처럼 PATTERN 자리에 변수 이름이 있는 구문에서, 변수 이름은 아주 단순한 형태의 패턴일 뿐입니다. 러스트는 표현식을 패턴과 비교하고, 찾은 이름에 값을 대입합니다. 그래서 let x = 5; 예에서 x는 이 패턴에 맞는 것을 변수 x에 바인딩하라는 뜻의 패턴입니다. 이름 x가 패턴 전체이므로, 이 패턴은 사실상 값이 무엇이든 모든 것을 변수 x에 바인딩하라는 뜻입니다.

let의 패턴 매칭 면을 더 분명히 보려면, 다음 코드처럼 let의 패턴으로 튜플을 해체해 봅니다.

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

여기서는 튜플을 패턴과 맞춥니다. 러스트는 값 (1, 2, 3)을 패턴 (x, y, z)와 비교해 값이 패턴에 맞는다는 것을 확인합니다. 두 원소의 수가 같기 때문입니다. 그래서 러스트는 1을 x에, 2를 y에, 3을 z에 바인딩합니다. 이 튜플 패턴은 그 안에 세 개의 개별 변수 패턴을 중첩한 것이라고 생각할 수 있습니다.

패턴의 원소 수가 튜플의 원소 수와 맞지 않으면, 전체 타입이 맞지 않아 컴파일러 오류가 납니다. 예를 들어 다음 코드는 원소가 셋인 튜플을 변수 두 개로 해체하려는 시도이며, 동작하지 않습니다.

src/main.rs (컴파일되지 않음)
fn main() {
    let (x, y) = (1, 2, 3);
}
error[E0308]: mismatched types
 --> src/main.rs:2:9
  |
2 |     let (x, y) = (1, 2, 3);
  |         ^^^^^^   --------- this expression has type `({integer}, {integer}, {integer})`
  |         |
  |         expected a tuple with 3 elements, found one with 2 elements
  |
  = note: expected tuple `({integer}, {integer}, {integer})`
             found tuple `(_, _)`

For more information about this error, try `rustc --explain E0308`.

이 오류를 고치려면 패턴에서 값 무시하기에서 볼 _나 ..로 튜플의 값 하나 이상을 무시할 수 있습니다. 문제가 패턴에 변수가 너무 많다는 것이라면, 변수를 빼 변수의 수가 튜플의 원소 수와 같게 하는 것이 해결책입니다.

함수 매개변수

함수 매개변수도 패턴이 될 수 있습니다. 다음 코드는 i32 타입의 매개변수 x 하나를 받는 foo라는 함수를 선언하며, 이제는 익숙해 보일 것입니다.

fn foo(x: i32) {
    // 여기에 코드
}

x 부분이 패턴입니다. let에서 했듯, 함수의 인수에서도 튜플을 패턴에 맞출 수 있습니다. 다음 코드는 함수에 넘긴 튜플의 값을 나눕니다.

src/main.rs
fn print_coordinates(&(x, y): &(i32, i32)) {
    println!("Current location: ({x}, {y})");
}

fn main() {
    let point = (3, 5);
    print_coordinates(&point);
}

이 코드는 Current location: (3, 5)를 출력합니다. 값 &(3, 5)가 패턴 &(x, y)에 맞으므로, x는 값 3이고 y는 값 5입니다.

클로저: 자신의 환경을 캡처하는 익명 함수에서 이야기했듯 클로저는 함수와 비슷하므로, 클로저의 매개변수 목록에서도 함수의 매개변수 목록에서와 같은 방식으로 패턴을 쓸 수 있습니다.

지금까지 패턴을 쓰는 여러 방법을 보았지만, 패턴을 쓸 수 있는 곳마다 패턴이 똑같이 동작하지는 않습니다. 어떤 곳에서는 패턴이 반박 불가능해야 하고, 다른 곳에서는 반박 가능해도 됩니다. 다음에 이 두 개념을 이야기합니다.

정리

  • 패턴은 리터럴, 해체, 변수, 와일드카드, 자리 표시자를 조합해 데이터의 모양을 나타내며, 값이 그 모양에 맞으면 이름 붙은 조각을 쓸 수 있습니다.
  • match의 갈래는 모두 모여 가능한 모든 값을 덮어야 하고, _는 무엇이든 맞추되 바인딩하지 않습니다.
  • if let은 else if, else if let과 섞어 쓸 수 있지만 철저한지 확인하지 않으며, while let은 패턴이 맞는 동안 반복합니다.
  • for의 패턴, let 구문, 함수와 클로저의 매개변수도 패턴이며, 튜플을 해체할 때 원소 수가 맞지 않으면 E0308 오류가 납니다.
  • let...else는 반박 가능한 패턴을 허용하고, 맞지 않으면 else에서 흐름을 벗어나야 합니다.

연습 문제

1. 무엇이 출력될까

이 글의 배경색 예제에서 (가) favorite_color를 Some("red")로, (나) age를 "twenty".parse()로, (다) is_tuesday를 true로, age를 "18".parse()로 바꾸면 각각 무엇이 출력되나요? 각 경우의 다른 값은 원래대로입니다.

해설 보기

(가)는 첫 조건이 맞아 Using your favorite color, red, as the background를 출력합니다. (나)는 좋아하는 색이 없고 화요일도 아니며, "twenty"를 u8로 파싱하지 못해 Err이므로 마지막 else로 가서 Using blue as the background color를 출력합니다. (다)는 좋아하는 색이 없고 is_tuesday가 참이므로 age를 보기 전에 Tuesday is green day!를 출력합니다.

2. 고쳐 쓰기

let (x, y) = (1, 2, 3);이 컴파일되도록 고치는 방법을 두 가지 쓰세요. 세 번째 값만 쓰고 싶다면 어떻게 쓰나요?

해설 보기

원소 수를 맞춰 let (x, y, z) = (1, 2, 3);으로 쓰거나, 쓰지 않을 값을 _나 ..로 무시해 let (x, y, _) = (1, 2, 3); 또는 let (x, y, ..) = (1, 2, 3);으로 씁니다. 세 번째 값만 필요하다면 let (.., z) = (1, 2, 3);이나 let (_, _, z) = (1, 2, 3);처럼 씁니다.

다음 글 반박 가능성: 패턴이 매칭에 실패할지의 여부에서는 패턴이 실패할 수 있는지에 따라 쓸 수 있는 곳이 어떻게 달라지는지 살펴봅니다.