有一些文本文件需要逐行操作。我写了一个 withFile
功能如下:
let withFile fn handle =
let rec iter_lines fh =
try
handle (input_line fh);
iter_lines fh
with _ -> close_in fh in
iter_lines (open_in fn);;
所以我可以将每个文件操作为:
withFile "file1.txt" (fun line -> (*...*))
withFile "file2.txt" (fun line -> (*...*))
...
但是当我不想处理所有行时,我不确定如何优雅地退出。例如:
withFile "file3.txt" (fun line ->
(*when the line meets some condition, i will exit without handling other lines*)
);
任何建议表示赞赏!
最佳答案
您的职能 iter_lines
不是尾递归的,这意味着如果您以这种方式处理非常大的文件,您可能会耗尽堆栈空间。它不是尾递归的原因是它必须建立和拆除 try ... with
异常捕获机制。
除此之外,这对我来说真的很好。这种高阶函数就是 OCaml(和 FP)的全部内容。
使其尾递归的一种方法是将异常处理移出包含函数。我还会更具体地说明您要处理的异常。所以你得到这个:
let withFile fn handle =
let rec iter_lines fh =
handle (input_line fh);
iter_lines fh
in
let fh = open_in fn in
try iter_lines fh
with End_of_file -> close_in fh
如果您希望能够提前退出,一种简单的方法是让您的句柄函数返回一个 bool 值,告诉您是否继续处理行。你最终会得到这样的结果:
let withFile fn handle =
let rec iter_lines fh =
if handle (input_line fh) then
iter_lines fh
in
let fh = open_in fn in
try iter_lines fh
with End_of_file -> close_in fh
如果您希望能够使用异常提前退出,您需要捕获
withFile
中的所有异常。 , 关闭文件,然后重新引发除 End_of_file
之外的任何异常.这为您提供了如下所示的代码:let withFile fn handle =
let rec iter_lines fh =
handle (input_line fh);
iter_lines fh
in
let fh = open_in fn in
try iter_lines fh
with e ->
(close_in fh; if e <> End_of_file then raise e)
关于exception - 使用异常中断对文件行的迭代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8101735/