단일 조건의 참·거짓을 평가할 때는 if를 사용합니다. 값의 구조나 타입에 따라 결과를 선택할 때는 match를 사용합니다. 각 요소에 동일한 작업을 반복할 때는 for를 사용합니다. match와 for 내부의 패턴은 데이터를 검사하는 동시에 필요한 요소에 이름을 바인딩합니다.
예제 실행하기
다음 코드를 data-control.tpz로 저장합니다.
record 학습과제 {
제목: string,
분: int,
완료: bool = false,
}
function 속도(과제: 학습과제) -> string {
if 과제.완료 {
return "done"
}
match 과제.분 {
case 1..15 => "quick"
case 16..30 => "focused"
case _ => "deep"
}
}
let 과제들: Array<학습과제> = [
학습과제 { 제목: "Run first program", 분: 10, 완료: true },
학습과제 { 제목: "Build application", 분: 25 },
]
let mut 남음 = 0
for 과제 in 과제들 {
if !과제.완료 {
남음 = 남음 + 과제.분
}
print("{과제.제목}: {속도(과제)}")
}
print("remaining: {남음} minutes")먼저 검사한 뒤 실행합니다.
topaz check data-control.tpz
topaz run data-control.tpz결과는 배열의 순서를 따릅니다.
Run first program: done
Build application: focused
remaining: 25 minutes코드가 내리는 세 가지 결정
반복문은 배열의 각 항목을 task라는 이름에 바인딩합니다. 안쪽의 if는 "이 작업이 미완료 상태인가?"라는 단일 참·거짓 조건만 판단합니다. 여러 경우로 분기하거나 값의 내부 구조를 추출할 필요가 없습니다.
양쪽 결과가 모두 필요하다면 if condition { ... } else { ... } 구문을 사용합니다. 두 분기가 서로 호환되는 값을 반환할 경우 if 구문 전체가 표현식의 평가 결과가 됩니다.
속도 함수는 완료된 과제를 if로 먼저 처리합니다. 이어지는 match는 과제.분을 한 번 평가한 뒤, 상단부터 case를 순차적으로 검사합니다. 1..15와 16..30은 범위 패턴에 해당합니다. 마지막 _는 나머지 정수를 모두 받아 처리하므로 모든 입력값에 대한 결과가 반환됩니다.
| 선택 | 알맞은 상황 | 만들어지는 결과 |
|---|---|---|
if | 단일 조건으로 분기할 때 | 각 분기가 호환되는 값을 내면 해당 값, 그렇지 않으면 부수 효과만 수행하는 문장 |
match | 값에 의미 있는 구조나 타입이 여러 가지일 때 | 선택된 분기의 반환값 및 해당 분기 내에서 활용할 수 있는 패턴 바인딩 |
for | 정해진 순서로 모든 요소를 순회할 때 | 문장으로 사용 시 부수 효과 수행, 식으로 사용 시 본문 평가 결과를 모은 Array |
패턴은 검사와 바인딩을 함께 한다
리터럴 패턴과 범위 패턴은 일치 여부를 검사합니다. 과제처럼 식별자만 지정한 패턴은 일치하는 값을 해당 이름에 바인딩합니다. Some(값)이나 Err(메시지) 같은 생성자 패턴은 Option과 Result 내부의 값을 추출합니다. 레코드 패턴은 명시한 필드만 선택하여 추출합니다.
배열 패턴에서 남은 요소를 표시할 때는 ... 대신 ..를 사용합니다. case [head, ..tail] =>는 첫 항목을 head에 바인딩하고, 남은 항목은 Array 타입인 tail에 바인딩합니다. 나머지 값을 사용할 필요가 없을 때는 _로 처리합니다.
if let 패턴 = 값 { ... }은 매칭 성공 케이스 하나만 다룰 때 유용하며, 실패 경로는 필요한 경우에만 구성합니다. while let은 패턴이 더 이상 일치하지 않을 때까지 동일한 검사를 반복합니다. 두 구문이 생성한 바인딩은 변경할 수 없으며, 매칭 성공 블록 내부에서만 유효합니다.
흔한 실수
패턴 표현식에 [head, ...tail]을 사용해서는 안 됩니다. ...는 배열이나 함수 호출에서 전개 연산자로 사용됩니다. 리스트 패턴에서 나머지 요소를 지정하는 올바른 표기는 [head, ..tail]입니다.
열거형은 인스턴스를 생성할 때와 패턴으로 검사할 때의 표기가 다릅니다. 값 생성 시에는 상태.일시정지("review")처럼 열거형 이름을 포함합니다. 패턴 매칭에서는 case 일시정지(이유) =>처럼 배리언트 이름만 명시합니다.
선택에 영향을 주는 정확한 동작
- 값을 반환하는
if와match의 분기 결과는 서로 호환되어야 합니다. - 닫힌 열거형을
match하면 모든 배리언트를 다루는지 검증합니다. 가드가 결합된 분기는 완전성 판단 대상에서 제외됩니다. - 검증기가 모든 경우를 처리했다고 입증하지 못하면
_분기를 직접 작성합니다. - 패턴은 좌측에서 우측 방향으로 평가합니다. 불일치한 대안에서 생성된 바인딩은 다음 대안으로 전달되지 않습니다.
- 컬렉션 컴프리헨션에서 실패 가능 패턴이 일치하지 않으면 해당 항목을 건너뛰지 않고 런타임 오류가 발생합니다. 항목을 거르려면
if절을 직접 작성합니다. Array·정수 범위·Set·map.keys에는 정해진 순회 순서가 있습니다. 문자열은 직접 순회하지 않습니다.while과 문장 위치의for는 값을 생성하지 않습니다. 식으로 작성한for는 본문 평가 결과를 소스 순서대로 수집합니다.
사용자 정의 패턴·반복자·생성기·실행 오류를 처리하는 제어 구조·while이나 for에 지정하는 레이블은 현재 언어 범위에 포함되지 않습니다.
학습 과정의 데이터와 제어 예제에서 이어서 살펴볼 수 있습니다. 패턴이 여는 데이터 구조는 레코드와 명목 데이터를 참고하세요. 순회와 필터링은 컬렉션과 컴프리헨션을 참고하세요.