Version française
Home     About     Download     Resources     Contact us    

This site is updated infrequently. For up-to-date information, please visit the new OCaml website at

Browse thread
[Caml-list] Why do input* and readdir throw End_of_file ... annoying!
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: 2003-06-06 (17:01)
From: Richard Jones <rich@a...>
Subject: [Caml-list] Why do input* and readdir throw End_of_file ... annoying!
Dear OCaml users,

I'm pretty convinced that having the input* functions and readdir
throw End_of_file when they run out of data is wrong. Instead
'readdir' (for example) should be prototyped as:

readdir : dir_handle -> string option

and the functions should return None when they run out of data.
Either that or alternative forms which don't throw exceptions should
be available.

The reason is it makes input* and readdir very hard to use since they
are throwing exceptions in what is essentially an un-exceptional case
(it's _normal_, not exceptional, to keep reading data until the end of
the stream).

Take a look at the attached code. I've wrapped up 'readdir' in a
function which hides the annoying exception (or course, this is
inefficient, but I don't have much choice). The code is reasonably
easy to understand. Please someone show me the elegant solution to
this problem which doesn't involve hiding the exception ...

An alternative would be, like Perl, to provide alternative forms
of input_line and readdir (in particular) which return a list of
lines/names in a single go, rather like:

  my @files = readdir DIR;

in Perl.

(Another minor point - do I need to call closedir, or will the garbage
collector do that for me?)


open Unix

type filesystem = File of string | Directory of filesystem list;;

let readdir_no_ex dirh =
    Some (readdir dirh)
    End_of_file -> None

let rec read_directory path =
  let dirh = opendir path in
  let rec loop () =
    let filename = readdir_no_ex dirh in
    match filename with
      None -> []
    | Some "." -> loop ()
    | Some ".." -> loop ()
    | Some filename ->
	let pathname = path ^ "/" ^ filename in
	let stat = lstat pathname in
	let this = if stat.st_kind = S_DIR then
	  Directory (read_directory pathname)
	  File pathname in
	this :: loop ()
  loop ()

let path = Sys.argv.(1);;
let fs = read_directory path;;

Richard Jones, Red Hat Inc. (London) and Merjis Ltd. Freshmeat projects:
NET::FTPSERVER is a full-featured, secure, configurable, database-backed
FTP server written in Perl:

To unsubscribe, mail Archives:
Bug reports: FAQ:
Beginner's list: