Еще одна простая реализация.
Давайте сначала определим тип, представляющий либо результат, либо исключение:
type 'a okko = Ok of 'a | Ko of exn
Затем определим capture_errors
:
let capture_errors fn = try Ok (fn ()) with e -> (Ko e);;
Вы можете их реализовать unwind_protect
:
let unwind_protect wind unwind =
let result = (capture_errors wind) in
begin
unwind ();
match result with
| Ok (result) -> result
| Ko (error) -> raise error
end;;
Выше последовательно последовательно выполните unwind
один раз.
Затем вы можете определить общую функцию with_
:
let with_ enter leave body =
let e = enter() in
unwind_protect
(fun () -> (body e))
(fun () -> (leave e)) ;;
Например, with_open_file
может быть определено как:
let with_open_file opener closer file fn =
with_
(fun () -> (opener file))
(fun (chan) -> (closer chan))
fn
Вы можете карри open_in
и close_in
в общем случае:
let with_input_file = with_open_file open_in close_in;;
Дляпример:
with_input "/etc/passwd" input_line