프로그램을 멈추지 않고 잘못된 학습 시간을 처리하며, 검사를 마칠 때마다 정리 동작을 실행해 보세요. 이어서 배열 접근 오류를 일으키고 원인이 된 인덱스를 고칩니다.
먼저 데이터와 제어를 마치세요. 설치한 토파즈와 같은 작업 폴더를 사용합니다.
올바른 입력과 잘못된 입력 처리하기
아래 코드를 failures-resources.tpz로 저장하세요.
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")같은 폴더에서 파일을 검사하고 실행하세요.
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 finishedOption과 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로 저장하세요.
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와 리소스에서 찾을 수 있습니다.