vog*_*vog 2 python ocaml raii with-statement
与 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
Run Code Online (Sandbox Code Playgroud)
即:OCaml中安全确保某个资源(打开的文件、数据库连接、HTTP 连接等)在某个时间点总是被释放的首选方式是什么?等待垃圾收集器在这里是没有选择的,异常不应该阻止资源被释放。
当然,在 OCaml 中,您始终可以使用 try-finally 并“手动”关闭文件,就像在 Python 中一样。但是,这种代码容易出错。这就是 Python 引入“with”语句的原因。什么 OCaml 习惯用法可以使这种代码更易于阅读且不易出错?
请注意,这个问题与在 OCaml 中模拟 try-with-finally的问题非常不同,因为这是更进一步的一步:我不只是想在 OCaml 中模拟 try-finally!(顺便说一下[%finally ...],Lwt做得很好。)我想更进一步,首先不需要编写那些 finally 子句——就像在 Python 中可以做到的那样。
还要注意,这个问题不是关于实现细节,而是关于习惯用法:所有可能的设计和解决方案中哪些在 OCaml 社区中获得了一些牵引力并被普遍接受?
JaneStreet 的 core_kernel 标准库替换以In_channel.with_file. 因此,如果您有机会使用 core_kernel,请参阅此处的使用示例: https: //dev.realworldocaml.org/imperative-programming.html#file-io
现在可以将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
Run Code Online (Sandbox Code Playgroud)
如今,甚至还有 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
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
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
Run Code Online (Sandbox Code Playgroud)
的let&操作者可以确保in_channel在当前范围的端部封闭(get_contents)。