어휘 범위를 벗어나기 전에 수행해야 할 정리 작업이 있다면 defer를 사용합니다.
해당 범위가 File 하나만 소유하는 경우에는 더 좁은 범위의 using 문을 사용할 수 있습니다.
이 구문은 리소스 획득, 하위 범위 지정, 암묵적 닫기 동작을 한데 묶습니다.
정리 순서 확인하기
프로그램과 동일한 위치에 defer-resources.txt라는 텍스트 파일을 만듭니다.
내용은 다음과 같습니다.
ready다음 코드를 defer-resources.tpz로 저장합니다.
function 메모검사(경로: string) -> Result<(), string> {
using 파일 = open(경로)? {
defer { print("body cleanup") }
let 메모 = 파일.read()?
print("note scalars: {메모.scalars().length}")
}
print("resource scope closed")
Ok(())
}
match 메모검사("defer-resources.txt") {
case Ok(_) => print("done")
case Err(메시지) => print("error: {메시지}")
}코드를 검사한 뒤 실행합니다.
topaz check defer-resources.tpz
topaz run defer-resources.tpz출력 순서는 다음과 같습니다.
note scalars: 6
body cleanup
resource scope closed
doneopen(경로)?는 파일 획득을 한 번만 시도합니다. 획득에 성공한 후에야 using 문이 암묵적 닫기 동작을 등록합니다. 본문 내에서 나중에 등록된 defer 블록이 먼저 실행되며, 암묵적 닫기까지 완료된 후에 resource scope closed로 넘어갑니다.
수명을 소유하는 형식 선택하기
| 상황 | 사용할 형식 |
|---|---|
| 현재 범위에 하나의 정리 호출이나 블록이 속한 경우 | defer call 또는 defer { ... } |
하나의 File이 하나의 하위 블록에 속한 경우 | using 파일 = open(경로)? { ... } |
| 획득·읽기·쓰기가 정상적으로 실패할 수 있는 경우 | Result를 반환하거나 분기 처리하고, 호환되는 함수 내부에서만 ? 사용 |
| 프로그램이 런타임 계약을 위반하는 경우 | 복구 가능한 정리 흐름이 아니라 실행 오류로 처리 |
단일 범위 내에 defer 구문이 여러 개 있으면 마지막에 등록된 것부터 역순으로 실행합니다. return, 접미사 ?, break, continue가 범위를 가로지를 때도 정리 작업을 먼저 마친 후 제어가 이동합니다. using 문으로 생성된 이름은 변경할 수 없으며 본문 내부에서만 유효합니다. 클로저가 File 값을 보관하는 것은 가능하지만, using 범위가 종료되면 암묵적 닫기가 실행됩니다. 해당 값을 계속 참조하더라도 리소스 수명이 연장되지는 않습니다.
Result 전파와 실행 오류는 다릅니다
open이 Err를 반환하면 아직 등록된 정리 작업이 없습니다. 파일.read()가 Err를 반환하는 경우는 다릅니다. 접미사 ? 연산자가 활성화된 using 범위를 가로지르므로, 등록된 정리 작업을 마친 뒤 오류가 메모검사 외부로 전파됩니다.
실행 오류가 제공하는 보장은 더 제한적입니다. 실행 오류는 그 자리에서 평가를 즉시 중단하며, 이후 어휘 범위의 defer나 using 정리 작업이 모두 실행된다고 언어가 보장하지는 않습니다. 지연된 정리 작업 자체에서 실행 오류가 발생할 경우 런타임의 기록·수집 정책을 따릅니다. 이 오류는 포착 가능한 값으로 다뤄지지 않으며, 이미 반환 중인 Err를 대체하지도 않습니다.
흔한 수정
파일 획득에 File.open(...)을 사용하지 마세요. 임의의 using 프로토콜을 새로 정의하지도 마세요. 올바른 획득 함수는 open(path) 하나뿐입니다. using 문은 불변인 단일 이름 하나와 File 하나만 받습니다.
using 본문 내부에서 close()를 직접 호출하더라도 등록된 닫기 시도가 취소되지는 않습니다. 닫은 이후의 동작이나 중복 닫기는 이식성을 제공하지 않으므로, 보통은 단일 소유자가 리소스를 한 번만 닫도록 구현해야 합니다.
정확한 경계
사용자 정의 정리 프로토콜, 다중 리소스의 동시 획득, 리소스 소유권 이전, 비동기 정리, 취소 시 정리, 호스트 예외 보장, 모듈 수명주기 정리는 현재 토파즈가 지원하는 동작이 아닙니다. 코드 생성 백엔드는 위 동작을 유지하거나 지원하지 않는 프로그램을 명확히 거부해야 합니다. 이 인터프리터의 실행 결과만으로 모든 백엔드가 동일하게 동작한다고 주장할 수는 없습니다.
실패와 리소스에서 안내형 예제를 다시 살펴보세요. Null·Option·결과·fault에서는 값 없음과 복구 가능한 실패를 비교합니다. 정확한 파일 연산은 파일과 리소스에서 확인할 수 있습니다.