Uitzonderingen gebruiken om uit een iteratie over de regels van een bestand te breken

Er zijn enkele tekstbestanden die regel voor regel moeten worden gemanipuleerd. Ik schreef een withFile -functie zoals hieronder:

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

Dus ik kan elk bestand manipuleren als:

withFile "file1.txt" (fun line -> (*...*))
withFile "file2.txt" (fun line -> (*...*))
...

Maar ik weet niet zeker hoe ik elegant moet afsluiten als ik niet alle regels wil afhandelen. Bijvoorbeeld:

withFile "file3.txt" (fun line ->
   (*when the line meets some condition, i will exit without handling other lines*)
);

Elke suggestie wordt gewaardeerd!

4

1 antwoord

Uw functie iter_lines is niet tail recursief, wat betekent dat u waarschijnlijk uw stackruimte zult uitputten als u op deze manier een zeer groot bestand verwerkt. De reden dat het niet staartrecursief is, is dat het het try ... with -mechanisme moet vaststellen en afbreken om uitzonderingen op te vangen.

Anders dan dat, ziet dit er echt goed uit voor mij. Dit soort hogere-orde functie is waar OCaml (en FP) over gaat.

Een manier om het recursief te maken is door de uitzonderingsafhandeling naar de bevattende functie te verplaatsen. Ik zou ook meer specifiek willen zijn over de uitzondering die u wilt hanteren. Dus je krijgt dit:

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

Als u vroegtijdig wilt afsluiten, kunt u op één eenvoudige manier uw handle-functie teruggeven aan een boolean die aangeeft of de verwerking van regels moet doorgaan of niet. Je zou eindigen met zoiets als dit:

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

Als u een uitzondering wilt gebruiken om vroegtijdig af te sluiten, moet u alle uitzonderingen in metBestand vangen, het bestand sluiten en vervolgens eventuele uitzonderingen opnieuw genereren. dan End_of_file . Dit geeft je een code die er als volgt uitziet:

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)
6
toegevoegd