하나의 참·거짓 조건을 판단할 때는 if, 값의 형태나 종류에 따라 결과를 고를 때는 match, 각 항목에 같은 작업을 반복할 때는 for를 사용합니다. match와 for 안의 패턴은 데이터를 검사하면서 필요한 부분에 이름도 붙여 줍니다.
예제 실행하기
다음 코드를 data-control.tpz로 저장합니다.
record StudyTask {
title: string,
minutes: int,
done: bool = false,
}
function pace(task: StudyTask) -> string {
if task.done {
return "done"
}
match task.minutes {
case 1..15 => "quick"
case 16..30 => "focused"
case _ => "deep"
}
}
let tasks: Array<StudyTask> = [
StudyTask { title: "Run first program", minutes: 10, done: true },
StudyTask { title: "Build application", minutes: 25 },
]
let mut remaining = 0
for task in tasks {
if !task.done {
remaining = remaining + task.minutes
}
print("{task.title}: {pace(task)}")
}
print("remaining: {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 전체도 값이 됩니다.
pace는 완료된 작업을 먼저 if로 처리합니다. 이어지는 match는 task.minutes를 한 번 계산한 뒤 case를 위에서부터 차례로 검사합니다. 1..15와 16..30은 범위 패턴입니다. 마지막 _는 나머지 모든 정수를 받으므로 어떤 입력에도 결과가 생깁니다.
| 선택 | 알맞은 상황 | 만들어지는 결과 |
|---|---|---|
if | 하나의 조건으로 분기할 때 | 각 분기가 호환되는 값을 내면 그 값, 아니면 효과만 있는 문장 |
match | 값에 의미 있는 형태나 종류가 여러 개일 때 | 선택된 가지의 값과 그 가지 안에서 쓸 수 있는 패턴 바인딩 |
for | 정해진 순서로 모든 항목을 방문할 때 | 문장으로 쓰면 효과, 식으로 쓰면 본문 결과를 모은 Array |
패턴은 검사와 바인딩을 함께 한다
리터럴 패턴과 범위 패턴은 값이 맞는지 검사합니다. task처럼 이름만 쓴 패턴은 맞은 값을 그 이름에 연결합니다. Some(value)와 Err(message) 같은 생성자 패턴은 Option과 Result의 내부 값을 꺼냅니다. 레코드 패턴은 이름을 지정한 필드를 선택합니다.
배열 패턴의 나머지 표시는 ...가 아니라 ..입니다. case [head, ..tail] =>는 첫 항목을 head에, 남은 항목을 Array인 tail에 연결합니다. 나머지 값을 사용할 필요가 없다면 _로 받습니다.
if let pattern = value { ... }은 성공하는 형태 하나와 선택적인 실패 경로만 필요할 때 유용합니다. while let은 패턴이 더 이상 맞지 않을 때까지 같은 검사를 반복합니다. 두 형식에서 만든 바인딩은 변경할 수 없으며 성공 본문 안에서만 보입니다.
흔한 실수
패턴에 [head, ...tail]을 쓰면 안 됩니다. ...는 배열이나 함수 호출에서 값을 펼칠 때 사용합니다. 목록 패턴의 올바른 나머지 표기는 [head, ..tail]입니다.
열거형을 만들 때와 패턴으로 검사할 때의 표기도 다릅니다. 값은 Status.Paused("review")처럼 열거형 이름을 붙여 만들지만, 패턴에서는 case Paused(reason) =>처럼 변형 이름만 씁니다.
선택에 영향을 주는 정확한 동작
- 값을 만드는
if와match의 분기 결과는 서로 호환되어야 합니다. - 닫힌 열거형을
match하면 모든 변형을 다루는지 검사합니다. 가드가 붙은 가지는 완전성 판단에 포함되지 않습니다. - 검사기가 모든 경우를 다뤘다고 증명할 수 없다면
_가지를 명시합니다. - 패턴은 왼쪽에서 오른쪽으로 검사합니다. 실패한 대안에서 만든 바인딩은 다음 대안으로 새지 않습니다.
- 컬렉션 컴프리헨션에서 실패 가능한 패턴이 맞지 않으면 항목을 건너뛰는 것이 아니라 실행 오류가 납니다. 항목을 거르려면
if절을 명시합니다. Array, 정수 범위,Set,map.keys에는 정해진 순회 순서가 있습니다. 문자열은 직접 순회하지 않습니다.while과 문장 위치의for는 값을 만들지 않습니다. 식으로 사용한for는 본문 결과를 소스 순서대로 모읍니다.
사용자 정의 패턴과 반복자, 생성기, 실행 오류를 잡는 제어 형식, while이나 for에 붙이는 레이블은 현재 언어 범위에 포함되지 않습니다.
학습 과정의 데이터와 제어 예제에서 이어서 살펴볼 수 있습니다. 패턴이 여는 데이터 형태는 레코드와 명목 데이터, 순회와 필터링은 컬렉션과 컴프리헨션을 참고하세요.