From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (from majordomo@localhost) by pauillac.inria.fr (8.7.6/8.7.3) id VAA12897; Fri, 6 Jun 2003 21:27:42 +0200 (MET DST) X-Authentication-Warning: pauillac.inria.fr: majordomo set sender to owner-caml-list@pauillac.inria.fr using -f Received: from nez-perce.inria.fr (nez-perce.inria.fr [192.93.2.78]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id VAA13144 for ; Fri, 6 Jun 2003 21:27:41 +0200 (MET DST) Received: from epexch01.qlogic.org ([63.170.40.3]) by nez-perce.inria.fr (8.11.1/8.11.1) with ESMTP id h56JReT00324 for ; Fri, 6 Jun 2003 21:27:40 +0200 (MET DST) Received: from epmailtmp.qlogic.org ([10.20.33.254]) by epexch01.qlogic.org with Microsoft SMTPSVC(5.0.2195.5329); Fri, 6 Jun 2003 14:29:00 -0500 Received: from [10.20.33.146] ([10.20.33.146]) by epmailtmp.qlogic.org with Microsoft SMTPSVC(5.0.2195.4905); Fri, 6 Jun 2003 14:29:00 -0500 Date: Fri, 6 Jun 2003 14:44:57 -0500 (CDT) From: Brian Hurt X-X-Sender: Reply-To: Brian Hurt To: Richard Jones cc: Subject: Re: [Caml-list] Why do input* and readdir throw End_of_file ... annoying! In-Reply-To: <20030606185111.GA3545@redhat.com> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-OriginalArrivalTime: 06 Jun 2003 19:29:00.0612 (UTC) FILETIME=[E1AC4840:01C32C61] X-Spam: no; 0.00; qlogic:01 caml-list:01 readdir:01 recursion:01 beginners:01 accum:01 checker:01 extlib:01 enum:01 cap:99 inchan:01 outchan:01 char:01 ocaml:01 rec:01 Sender: owner-caml-list@pauillac.inria.fr Precedence: bulk On Fri, 6 Jun 2003, Richard Jones wrote: > On Fri, Jun 06, 2003 at 01:49:55PM -0500, Brian Hurt wrote: > > The problem with try/with is that it's way to easy to break tail recursion > > using try/with. About every other week someone comes to the Ocaml > > beginners list where they are doing something like: > > What's a good way to read all the lines of a file into a list? I > can put it into the OCaml tutorial I'm writing. The way I'd recommend doing it: let read_all_lines chan = let rec loop accum = let line, eof = try (input_line chan), true with End_of_file -> "", false in if eof then accum else loop (line :: accum) in List.rev (loop []) The original poster's idea of a function: let my_input_line chan = try Some(input_line chan) with End_of_file -> None has the advantage of enlisting the type checker to make sure you handle the eof condition correctly everywhere. For those seeking best performance, using the ExtLib would allow you to do the following: let read_all_lines chan let e = Enum.from (fun () -> try input_line chan with End_of_file -> raise No_more_elements) in ExtList.of_enum e This has the effect of eliminating the List.rev. Although at this point you should be very tempted to just keep it an enum, which are in some ways easier to work with than lists, and you don't read the data until you need it. For example, to read in all the lines of one file, make them upper case, and write them out to another file, you might write: let cap_all_lines inchan outchan let e = Enum.from (fun () -> try input_line inchan with End_of_file -> raise No_more_elements) in let e' = Enum.map String.capitalize e in Enum.iter (fun x -> output_string outchan x; output_char '\n') e' The advatange of this method is that only one line at a time needs to be in memory. Brian ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners