gpt4 book ai didi

exception-handling - 在 OCaml 中模拟 try-with-finally

转载 作者:行者123 更新时间:2023-12-04 07:54:39 25 4
gpt4 key购买 nike

OCaml 的 try .. with不提供 finally子句像Java。不过,这会很有用,尤其是在处理副作用时。例如,我喜欢打开一个文件,将打开的文件传递给一个函数,然后关闭它。如果函数引发异常,我必须捕获它以便有机会关闭文件。当打开多个文件时,这会变得越来越复杂,而且打开本身也可能会失败。是否有一个既定的编程模式来处理这个问题?

下面是一个说明问题的简单函数。功能 f如果 path,则应用于属于文件的 channel 提供和 stdin除此以外。因为没有finally子句,close_in io出现两次。

let process f  = function 
| Some path ->
let io = open_in path in
( (try f io with exn -> close_in io; raise exn)
; close_in io
)
| None -> f stdin

最佳答案

Is there an established programming pattern to deal with this?



是的,将资源清理与异常处理分离的包装函数。我所做的是使用通用包装器, unwind (我更习惯使用的 LISP 主义):
let unwind ~(protect:'a -> unit) f x =
try let y = f x in protect x; y
with e -> protect x; raise e

这是一个简单的包装器,它没有正确解释 protect 中引发的异常;一个经过全面检查的包装器,可确保 protect即使它本身失败也只调用一次可能是 Yaron Minski's ,或者我认为更清楚一点的这个:
let unwind ~protect f x =
let module E = struct type 'a t = Left of 'a | Right of exn end in
let res = try E.Left (f x) with e -> E.Right e in
let () = protect x in
match res with
| E.Left y -> y
| E.Right e -> raise e

然后,我根据需要定义特定实例,例如:
let with_input_channel inch f =
unwind ~protect:close_in f inch

let with_output_channel otch f =
unwind ~protect:close_out f otch

let with_input_file fname =
with_input_channel (open_in fname)

let with_output_file fname =
with_output_channel (open_out fname)

具体原因我切换参数 with_功能是我觉得高阶编程更方便;特别是,通过定义一个应用程序操作符 à la Haskell,我可以写:
let () = with_output_file "foo.txt" $ fun otch ->
output_string otch "hello, world";
(* ... *)

语法不是很重。对于更复杂的示例,请考虑以下内容:
let with_open_graph spec (proc : int -> int -> unit) =
unwind ~protect:Graphics.close_graph (fun () ->
proc (Graphics.size_x ()) (Graphics.size_y ());
ignore (Graphics.wait_next_event [Graphics.Button_down]);
ignore (Graphics.wait_next_event [Graphics.Button_up]))
(Graphics.open_graph spec)

可以与类似 with_open_graph " 400x300" $ fun width height -> (*...*) 的电话一起使用.

关于exception-handling - 在 OCaml 中模拟 try-with-finally,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11276985/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com