2013-06-30 3 views
0

리소스 사용 중에 예외가 발생할 때 리소스를 릴리스하고 싶습니다.표준 ML 예외 및 리소스

C++에서이 작업은 쉽습니다. 나는 어떤 일이 생기더라도 자동으로 호출되는 소멸자에 릴리스를 놓았습니다. 자바에서는 'finally'절을 사용합니다. 표준 ML에서 이와 동일한 작업을 수행하는 방법은 무엇입니까?

내가 변수 패턴 'E'와 모든 예외를 잡기 위해 노력을 재 레이즈 :

datatype FileReadResult = FileReadOkay of string | FileReadError 

fun read_file (file_path_string : string) : FileReadResult = 
    let 
     val istream = TextIO.openIn file_path_string 
      (* this file is my resource *) 
    in 
     TextIO.closeIn istream; 
     FileReadOkay "" (* the content of the file will go here *) 
     handle e => (TextIO.closeIn istream; raise e) 
    end 
    handle Io => FileReadError 

제 컴파일러 (MLton가)를 받아,하지만 난 ML의 새로운이기 때문에, 여기에 대한 질문 이것이 정말로 옳은지에 대한 확신 | 최선의 방법.

이 일반적인 디자인 패턴이기 때문에

, 나는 그것을 표현하기 위해 아래의 효용 함수를 만들었습니다 :

(* Uses the given resource in the given way while releasing it if any exception occurs. *) 
fun use_resource (resource : 'Resource) (releaser : 'Resource -> unit) (usage : unit -> 'Result) : 'Result = 
    let 
     val r = usage() 
    in 
     releaser resource; 
     r 
    end 
    handle e => (releaser resource; raise e) 

이 기능은 C#을에서 '사용'기능과 같은 역할을한다.

답변

3

예, 즉 두 가지주의 사항과 함께, 일반적인 패턴입니다 :

  1. 내부 handle

    지금까지 포기하지에만 코드에서 FileReadOkay "", 주위에있다. 처리기가 모든 코드에 적용될 수 있도록 코드의 큰 부분에 괄호를 넣으려고합니다.
  2. 외부 처리기가 Io을 포착합니다. 여기서 IO.Io _을 의미한다고 생각하면 예외로 잡을 것입니다 (Io은 임의의 새로운 변수입니다).

자주 발생하는 경우 함수로 추상화하려고 할 수도 있습니다.

(* withTextFile : string -> (TextIO.instream -> 'a) -> 'a 
fun withTextFile name f = 
    let 
     val is = TextIO.openIn name 
    in 
     (f is before TextIO.closeIn is) 
     handle e => (TextIO.closeIn is; raise e) 
    end 

의 라인을 따라 무언가 (중위 연산자 before는 좌측과 우측 표현식을 평가하고 이전의 결과를 반환한다). 다음과 같이 사용하십시오 :

fun echo file = withTextFile file (fn is => print(TextIO.inputAll is)) 
+0

감사합니다. – libeako

+0

특히 Io에 관한 경고에 감사드립니다 <-> IO.Io _ 오류. 의미의이 "가변 패턴"기능은 오류가 발생하기 쉬운 것처럼 보입니다 - 제가 약간의 오타를 만든다면 컴파일러는 경고하지 않고 전혀 다른 것을 자동으로 할 것입니다. 가변 패턴으로 해석되는 것을 피하기 위해 항상 유형을 한정해야한다고 생각합니다. – libeako

+0

필자는이 기능이 적어도 예외 처리기를 사용하면 약간의 오류가 발생하기 쉽다는 점에 동의합니다 (정상적인 패턴에서는 이러한 오류로 인해 대개 "중복 일치"경고가 발생합니다). 나는 생성자와 변수를 대소 문자로 구별하는 OCaml/Haskell 솔루션보다 s.th를 선호한다. –