참·거짓 조건 하나를 판단할 때는 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에 붙이는 레이블은 현재 언어 범위에 포함되지 않습니다.
학습 과정의 데이터와 제어 예제에서 이어서 살펴볼 수 있습니다. 패턴이 여는 데이터 형태는 레코드와 명목 데이터를 참고하세요. 순회와 필터링은 컬렉션과 컴프리헨션을 참고하세요.