2011-11-12 3 views
4

行ごとに操作する必要のあるテキストファイルがあります。だから私は、各ファイルを操作することができます例外を使用してファイルの行にわたる繰り返しを中断する

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機能を書いた

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*) 
); 

ご了承ください。

答えて

6

あなたの機能iter_linesを使用すると、非常に大きなファイルをこのように処理する場合は、おそらくあなたのスタック空間を使い果たすだろう意味し、末尾再帰ではありません。それが末尾再帰的でない理由は、例外をキャッチするためにtry ... withメカニズムを確立し、解消する必要があるからです。

それ以外は、これは本当によかったです。この種の高次関数は、OCaml(とFP)のすべてです。

1つの方法は、末尾再帰を含む関数に出て例外処理を移動させることであることを確認します。私はまた、あなたが処理したい例外についてより具体的になります。だから、あなたはこれを取得:

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 

をあなたが早期に終了することができるようにしたい場合は、1つの簡単な方法は、あなたのハンドル関数が処理ラインを継続するかどうかを指示するブール値を返すことです。あなたはこのようなものに終わるだろう:

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) 
:これはあなたにこのようなコードを提供します
関連する問題