토파즈 배우기

실패와 리소스

Option과 Result로 잘못된 학습 시간을 거절하고, defer의 정리 동작을 확인하며, 배열 접근 오류를 고칩니다.

프로그램을 멈추지 않고 잘못된 학습 시간을 처리하며, 검사를 마칠 때마다 정리 동작을 실행해 보세요. 이어서 배열 접근 오류를 일으키고 원인이 된 인덱스를 고칩니다.

먼저 데이터와 제어를 마치세요. 설치한 토파즈와 같은 작업 폴더를 사용합니다.

올바른 입력과 잘못된 입력 처리하기

아래 코드를 failures-resources.tpz로 저장하세요.

TOPAZ
record 학습과제 {
    제목: string,
    분: int,
}

function 분해석(텍스트: string) -> Result<int, string> {
    match toInt(텍스트) {
        case Some(값) if 값 > 0 => Ok(값)
        case _ => Err("minutes must be a positive integer")
    }
}

function 과제만들기(제목: string, 분문자열: string) -> Result<학습과제, string> {
    let 분 = 분해석(분문자열)?
    Ok(학습과제 { 제목: 제목, 분: 분 })
}

function 검사(분문자열: string) -> () {
    print("input: {분문자열}")
    defer { print("inspection finished") }
    match 과제만들기("Build application", 분문자열) {
        case Ok(과제) => print("ready: {과제.제목}, {과제.분} minutes")
        case Err(메시지) => print("cannot add task: {메시지}")
    }
}

검사("25")
검사("later")

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

BASH
topaz check failures-resources.tpz
topaz run failures-resources.tpz

두 명령 모두 종료 코드 0으로 끝납니다. 프로그램은 잘못된 입력을 알리고 정상적으로 진행합니다.

출력
input: 25
ready: Build application, 25 minutes
inspection finished
input: later
cannot add task: minutes must be a positive integer
inspection finished

Option과 Result를 따라 입력 읽기

Option은 값이 있을 수도, 없을 수도 있음을 나타냅니다. toInt("25")는 Some(25)를 반환합니다. toInt("later")는 정수로 읽을 수 없어 None을 반환합니다.

Result는 성공한 값을 Ok에, 오류 값을 Err에 담습니다. 분해석은 읽은 정수가 값 > 0을 만족하면 Ok(값)을 반환합니다. 값이 없거나 0 또는 음수이면 설명을 담은 Err를 반환합니다.

과제만들기에서 분해석(분문자열) 뒤의 ?는 Ok 안의 정수를 꺼냅니다. Err를 받으면 과제만들기를 즉시 끝내고 그 오류를 반환합니다. 이때는 과제를 만들지 않습니다. 두 함수가 문자열 오류를 담는 호환 가능한 Result를 반환하므로 이렇게 전달할 수 있습니다.

검사는 반환된 결과에 match를 적용해 새 과제나 오류 메시지를 출력합니다.

함수를 마칠 때 정리 동작 실행하기

defer는 실행이 자신을 둘러싼 스코프를 나갈 때 할 동작을 등록합니다. 여기서 스코프는 검사의 본문입니다. 그래서 검사를 마칠 때마다 inspection finished가 나옵니다. "later"의 오류 메시지도 프로그램이 처리하는 일반 반환값입니다.

열어 둔 파일을 닫는 등의 정리 작업에 defer를 쓰세요. return이나 ?로 스코프를 나갈 때도 등록한 정리 작업을 실행합니다. 실행 오류인 fault가 발생하면 실행을 즉시 멈추며, 그 뒤의 정리 동작은 정해져 있지 않습니다. 예상되는 입력 실패는 Result로 처리해 정상적으로 정리 작업까지 진행하세요.

잘못된 배열 인덱스 찾아 고치기

다음 프로그램은 별도 파일 intentional-fault.tpz로 저장하세요.

TOPAZ
let 과제들 = ["Run first program", "Build application"]
print(과제들[2])

topaz run intentional-fault.tpz를 실행하세요. 명령은 0이 아닌 종료 코드로 끝나며 잘못 접근한 위치를 알립니다.

출력
error[TPZ4001]: index 2 is out of bounds for an array of length 2
 --> intentional-fault.tpz:2:7
  |
2 | print(과제들[2])
  |       ^^^^^^

두 요소의 인덱스는 0과 1입니다. 인덱스 2는 없는 요소를 요청하므로 실행 오류가 발생해 실행이 멈춥니다. match나 ?가 처리할 Err 값은 나오지 않습니다.

2행의 과제들[2]를 과제들[1]로 고치고 다시 실행하세요. Build application을 출력하고 종료 코드 0으로 끝납니다.

값 없음과 잘못된 값 처리하기

상황사용할 구문이나 할 일
값이 없을 수 있음Some(값) 또는 None을 담는 Option
호출자가 성공 값이나 오류 설명을 받아야 함Ok(값) 또는 Err(오류)를 담는 Result
함수가 호출자에게 오류를 전달해야 함호환 가능한 반환 타입을 가진 함수 안에서 ? 사용
잘못된 연산으로 실행 오류가 발생함연산을 고치거나 실행 전에 입력값 확인
스코프를 나갈 때 정리할 작업이 있음defer로 정리 작업 등록

직접 해보기

failures-resources.tpz 끝에 검사("0")를 추가하세요. 추가될 출력 줄을 예상한 뒤 파일을 검사하고 실행하세요.

정답 보기

먼저 input: 0이 나옵니다. 0은 값 > 0을 만족하지 않아 다음 줄에 cannot add task: minutes must be a positive integer가 나옵니다. 검사 스코프를 정상적으로 나가므로 마지막 줄은 inspection finished입니다.

다음 실습으로 이어가기

"later"가 None에서 Err로 바뀌는 과정과 ?가 오류를 반환하는 위치를 찾았다면 다음으로 넘어가세요. 추가한 0 입력에서 오류와 정리 문구가 나오고, 고친 배열 접근이 성공하는지도 확인하세요.

첫 애플리케이션에서 학습 계획을 두 파일로 만들어 보세요. 세부 규칙은 Null·Option·결과·fault와 Defer와 리소스에서 찾을 수 있습니다.