데이터와 제어

패턴과 제어 흐름

if, match, for를 고르고 분기 결과를 따라가며 패턴으로 값을 꺼내는 방법을 설명합니다.

조건을 검사할 때는 if, 경우를 고를 때는 match, 항목마다 작업할 때는 for를 쓰세요. 예제를 따라 어떤 과제의 시간이 남은 시간에 더해지는지 확인해 보세요.

첫 프로그램을 따라 토파즈를 설치하세요. 여기서 쓰는 레코드와 배열은 데이터와 제어에서 먼저 익힐 수 있습니다.

과제를 분류하고 남은 시간 더하기

작업 폴더에 다음 코드를 data-control.tpz로 저장하세요.

TOPAZ
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")

같은 폴더에서 파일을 검사하고 실행하세요.

BASH
topaz check data-control.tpz
topaz run data-control.tpz

검사는 종료 코드 0으로 성공합니다. 실행하면 다음 결과를 출력합니다.

출력
Run first program: done
Build application: focused
remaining: 25 minutes

각 결정 따라가기

반복문은 배열의 각 항목에 과제라는 이름을 붙입니다. 완료한 과제는 !과제.완료가 거짓이므로 남음이 0을 유지합니다. 속도 함수는 match에 도달하기 전에 "done"을 반환합니다.

두 번째 과제는 미완료 상태입니다. 소요 시간 25분을 남음에 더합니다. 속도에서 25는 16..30에 해당하므로 "focused"를 반환합니다.

match는 과제.분을 한 번 계산하고 분기를 위에서 아래로 검사합니다. 각 case에는 패턴과 결과가 있습니다. 범위 패턴은 값이 어느 구간에 속하는지 검사합니다. _는 나머지 값을 모두 받으므로 다른 정수에는 "deep"을 반환합니다.

작업선택결과
참·거짓 조건으로 선택하기if선택한 분기 실행
값이나 값의 구조로 선택하기match선택한 분기의 값
순서대로 각 항목 처리하기for항목마다 본문 실행

양쪽 결과를 모두 처리하려면 if condition { ... } else { ... }를 쓰세요. if나 match를 값으로 쓰려면 각 분기의 결과 타입이 호환되어야 합니다. for를 식으로 쓰면 본문 결과를 Array에 모읍니다. 문장 위치의 for와 while은 동작을 수행하며 결과값을 만들지 않습니다.

패턴으로 값을 검사하고 이름 붙이기

패턴은 값을 검사하거나 이름을 붙이거나 내부 값을 꺼낼 수 있습니다. 리터럴·범위 패턴은 값을 검사합니다. 과제 같은 이름 패턴은 내용을 검사하지 않고 값에 이름을 붙입니다.

Some(값)은 Option에서 존재하는 값을 꺼냅니다. Err(메시지)는 Result에서 오류를 꺼냅니다. 레코드 패턴은 이름을 적은 필드를 꺼냅니다. 레코드와 열거형 선언은 레코드와 명목 데이터를 참고하세요.

배열 패턴 [head, ..tail]은 첫 항목을 head, 나머지를 배열 tail에 묶습니다. _는 이름을 붙이지 않고 값을 받습니다.

패턴이 맞을 때 블록을 실행하려면 if let 패턴 = 값 { ... }를 쓰세요. 불일치도 처리하려면 else를 붙이세요. while let은 패턴이 맞지 않을 때까지 반복합니다. 두 구문이 붙인 이름은 성공한 블록 안에서 보이며 변경할 수 없습니다.

패턴 고치기

배열 패턴의 [head, ...tail]은 [head, ..tail]로 고치세요. 점 세 개는 리터럴이나 호출에서 배열을 펼칩니다. 점 두 개는 패턴에서 나머지 항목을 모읍니다.

열거형 값은 상태.일시정지("review")처럼 열거형 이름을 붙여 만듭니다. 분기에서는 case 일시정지(이유) =>처럼 변형 이름을 씁니다.

모든 경우 처리하기와 순회 규칙

  • 열거형의 match는 선언된 모든 변형을 처리해야 합니다. 가드는 분기에 추가하는 조건이므로 가드가 있는 분기는 전체 처리 여부를 판단할 때 제외합니다.
  • 정적 검사로 모든 경우를 처리하는지 확인할 수 없다면 나머지를 받을 _ 분기를 넣으세요.
  • 패턴은 왼쪽부터 계산합니다. 일치하지 않은 대안에서 붙인 이름은 다음 대안에서 쓸 수 없습니다.
  • 컴프리헨션의 패턴이 맞지 않으면 실행 오류가 납니다. 뒤의 패턴으로 내부 값을 꺼내기 전에 if로 항목을 거르세요.
  • 배열·정수 범위·집합·map.keys에는 정해진 순회 순서가 있습니다. 문자열은 순회 전에 스칼라 연산을 거쳐야 합니다.
  • 사용자 정의 패턴·순회·제너레이터·예외 처리·while이나 for의 레이블은 지원하지 않습니다.

컬렉션을 고르고 값을 거르는 방법은 컬렉션과 컴프리헨션에서 이어집니다.