Skip to main content
 首页 » 编程设计

python之Python 的 "with"语句的 OCaml 对应项是什么(自动释放资源)

2025年05月04日15linjiqin

Python 的“with”语句对应的 OCaml 是什么?

with open('test.txt', 'r') as f: 
    # Do stuff with f 
# At this point, f will always be closed, even in case of exceptions 

即:OCaml 中的首选方式 是什么来安全地确保某个资源(打开的文件、数据库连接、HTTP 连接等)将始终在某个时间点被释放?在这里等待垃圾收集器是没有选择的,异常不应该阻止资源被释放。

当然,在 OCaml 中,您始终可以使用 try-finally 并“手动”关闭文件,就像在 Python 中一样。但是,这种代码很容易出错。这就是 Python 引入“with”语句的原因。使此类代码更易于阅读且不易出错的 OCaml 习语是什么?

请注意,这个问题与 Emulating try-with-finally in OCaml 的问题有很大不同。 ,因为这是更进一步:我不只是想在 OCaml 中模拟 try-finally! (顺便说一句,Lwt's [%finally ...] 做得很好。)我想更进一步,消除首先编写这些 finally 子句的需要——就像在 Python 中可以做的那样。

另请注意,这个问题不是关于实现细节,而是关于成语:在所有可能的设计和解决方案中,哪些在 OCaml 社区中获得了一定的吸引力并被普遍接受?

请您参考如下方法:

现在有Fun.protect这可能被认为(有效地)成语,因为它在标准库中。例如,

let get_contents file = 
  let ch = open_in file in 
  Fun.protect ~finally:(fun () -> close_in ch) begin fun () -> 
    let len = in_channel_length ch in 
    let bytes = Bytes.create len in 
    ignore (input ch bytes 0 len); 
    bytes 
  end 

现在,甚至有 let-operators 正在慢慢找到更频繁使用的方​​法,例如https://github.com/ocaml/ocaml/pull/9887

所以你可以定义一个 let-op 来使用一个文件,比如:

let ( let& ) ch fn = 
  Fun.protect ~finally:(fun () -> close_in ch) begin fun () -> 
    fn ch 
  end 

像这样使用它:

let get_contents file = 
  let& ch = open_in file in 
  let len = in_channel_length ch in 
  let bytes = Bytes.create len in 
  ignore (input ch bytes 0 len); 
  bytes 

let& 运算符确保 in_channel 在当前作用域结束时关闭 (get_contents)。