* [Caml-list] Why do input* and readdir throw End_of_file ... annoying!
@ 2003-06-06 17:01 Richard Jones
2003-06-06 17:30 ` Michal Moskal
2003-06-06 18:03 ` Ville-Pertti Keinonen
0 siblings, 2 replies; 14+ messages in thread
From: Richard Jones @ 2003-06-06 17:01 UTC (permalink / raw)
To: caml-list
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?)
Rich.
----------------------------------------------------------------------
open Unix
type filesystem = File of string | Directory of filesystem list;;
let readdir_no_ex dirh =
try
Some (readdir dirh)
with
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)
else
File pathname in
this :: loop ()
in
loop ()
;;
let path = Sys.argv.(1);;
let fs = read_directory path;;
--
Richard Jones, Red Hat Inc. (London) and Merjis Ltd. http://www.merjis.com/
http://www.annexia.org/ Freshmeat projects: http://freshmeat.net/users/rwmj
NET::FTPSERVER is a full-featured, secure, configurable, database-backed
FTP server written in Perl: http://www.annexia.org/freeware/netftpserver/
-------------------
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
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Why do input* and readdir throw End_of_file ... annoying!
2003-06-06 17:01 [Caml-list] Why do input* and readdir throw End_of_file ... annoying! Richard Jones
@ 2003-06-06 17:30 ` Michal Moskal
2003-06-06 18:03 ` Ville-Pertti Keinonen
1 sibling, 0 replies; 14+ messages in thread
From: Michal Moskal @ 2003-06-06 17:30 UTC (permalink / raw)
To: Richard Jones; +Cc: caml-list
On Fri, Jun 06, 2003 at 06:01:32PM +0100, Richard Jones wrote:
> (Another minor point - do I need to call closedir, or will the garbage
> collector do that for me?)
Even if it does, I wouldn't relay on it -- you never know when it runs,
and if your objects are actually GCed. So if there is risk of running
out of file descriptors -- close it.
--
: Michal Moskal :: http://www.kernel.pl/~malekith : GCS {C,UL}++++$ a? !tv
: PLD Linux ::::::::: Wroclaw University, CS Dept : {E-,w}-- {b++,e}>+++ h
-------------------
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
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Why do input* and readdir throw End_of_file ... annoying!
2003-06-06 17:01 [Caml-list] Why do input* and readdir throw End_of_file ... annoying! Richard Jones
2003-06-06 17:30 ` Michal Moskal
@ 2003-06-06 18:03 ` Ville-Pertti Keinonen
2003-06-06 18:43 ` Richard Jones
2003-06-06 18:49 ` Brian Hurt
1 sibling, 2 replies; 14+ messages in thread
From: Ville-Pertti Keinonen @ 2003-06-06 18:03 UTC (permalink / raw)
To: Richard Jones; +Cc: caml-list
> 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.
I don't think it's necessarily such a clear requirement, unless you are
assuming the interface for some particular language.
Since exceptions are reasonably inexpensive in O'Caml, and used for
things such as Not_found in basic collection types, using exceptions to
indicate the end of some particular set of values seems reasonable, to
me.
Writing a try ... with statement isn't really that different from a
match statement except for the fact that you can handle exceptional
circumstances generated by several expressions in the with ... part of
a try ... with statement - if anything, that's more permissive.
-------------------
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
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Why do input* and readdir throw End_of_file ... annoying!
2003-06-06 18:03 ` Ville-Pertti Keinonen
@ 2003-06-06 18:43 ` Richard Jones
2003-06-07 15:08 ` Eric C. Cooper
2003-06-06 18:49 ` Brian Hurt
1 sibling, 1 reply; 14+ messages in thread
From: Richard Jones @ 2003-06-06 18:43 UTC (permalink / raw)
Cc: caml-list
On Fri, Jun 06, 2003 at 09:03:38PM +0300, Ville-Pertti Keinonen wrote:
> Writing a try ... with statement isn't really that different from a
> match statement except for the fact that you can handle exceptional
> circumstances generated by several expressions in the with ... part of
> a try ... with statement - if anything, that's more permissive.
The problem is that there doesn't seem to be a way to write the
loop function using readdir. eg:
let rec loop () =
let filename = readdir dirh in
match filename with
| "." -> loop ()
| ".." -> loop ()
| filename ->
let pathname = path ^ "/" ^ filename in
let stat = lstat pathname in
let this = if stat.st_kind = S_DIR then
read_directory pathname
else
File pathname in
this :: loop ()
in
try
Directory (loop ())
with
End_of_file -> XXX what?
Because the exception is always raised (it's not an exception at all)
there's no way to return the result of the call to loop ().
Rich.
--
Richard Jones, Red Hat Inc. (London) and Merjis Ltd. http://www.merjis.com/
http://www.annexia.org/ Freshmeat projects: http://freshmeat.net/users/rwmj
C2LIB is a library of basic Perl/STL-like types for C. Vectors, hashes,
trees, string funcs, pool allocator: http://www.annexia.org/freeware/c2lib/
-------------------
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
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Why do input* and readdir throw End_of_file ... annoying!
2003-06-06 18:03 ` Ville-Pertti Keinonen
2003-06-06 18:43 ` Richard Jones
@ 2003-06-06 18:49 ` Brian Hurt
2003-06-06 18:51 ` Richard Jones
2003-06-06 23:08 ` Lauri Alanko
1 sibling, 2 replies; 14+ messages in thread
From: Brian Hurt @ 2003-06-06 18:49 UTC (permalink / raw)
To: Ville-Pertti Keinonen; +Cc: Richard Jones, caml-list
On Fri, 6 Jun 2003, Ville-Pertti Keinonen wrote:
> Since exceptions are reasonably inexpensive in O'Caml, and used for
> things such as Not_found in basic collection types, using exceptions to
> indicate the end of some particular set of values seems reasonable, to
> me.
>
> Writing a try ... with statement isn't really that different from a
> match statement except for the fact that you can handle exceptional
> circumstances generated by several expressions in the with ... part of
> a try ... with statement - if anything, that's more permissive.
>
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:
let rec read_all_lines chan accum =
try
let line = input_line chan in
read_all_lines chan (line :: accum)
with
End_of_file -> List.rev accum
Unfortunately, this is *not* tail recursive. Works fine on small files,
but when they try to run it on large files they stack overflow. Which
means you need to contort to take the recursion out of the try/with block.
Several different approaches to this are possible- but none with the
obviousness of the above code.
Personally, I'd like the following to be an efficient way to read all the
lines from a file into a list:
let rec read_all_lines chan =
try
let line = input_line chan in
line :: (read_all_lines chan)
with
End_of_file -> []
and have the compiler contort the code into an efficient, tail-recursive
form, with a combination of data structures with a hole and catch removal.
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
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Why do input* and readdir throw End_of_file ... annoying!
2003-06-06 18:49 ` Brian Hurt
@ 2003-06-06 18:51 ` Richard Jones
2003-06-06 19:09 ` [Caml-list] " Alan Post
2003-06-06 19:44 ` [Caml-list] " Brian Hurt
2003-06-06 23:08 ` Lauri Alanko
1 sibling, 2 replies; 14+ messages in thread
From: Richard Jones @ 2003-06-06 18:51 UTC (permalink / raw)
Cc: caml-list
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.
Rich.
--
Richard Jones, Red Hat Inc. (London) and Merjis Ltd. http://www.merjis.com/
http://www.annexia.org/ Freshmeat projects: http://freshmeat.net/users/rwmj
NET::FTPSERVER is a full-featured, secure, configurable, database-backed
FTP server written in Perl: http://www.annexia.org/freeware/netftpserver/
-------------------
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
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Caml-list] Re: Why do input* and readdir throw End_of_file ... annoying!
2003-06-06 18:51 ` Richard Jones
@ 2003-06-06 19:09 ` Alan Post
2003-06-06 19:44 ` [Caml-list] " Brian Hurt
1 sibling, 0 replies; 14+ messages in thread
From: Alan Post @ 2003-06-06 19:09 UTC (permalink / raw)
To: caml-list
In article <20030606185111.GA3545@redhat.com>, 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.
Use ExtLib, of course. :)
List.of_enum (input_enum chan)
-------------------
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
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Why do input* and readdir throw End_of_file ... annoying!
2003-06-06 18:51 ` Richard Jones
2003-06-06 19:09 ` [Caml-list] " Alan Post
@ 2003-06-06 19:44 ` Brian Hurt
1 sibling, 0 replies; 14+ messages in thread
From: Brian Hurt @ 2003-06-06 19:44 UTC (permalink / raw)
To: Richard Jones; +Cc: caml-list
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
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Why do input* and readdir throw End_of_file ... annoying!
2003-06-06 18:49 ` Brian Hurt
2003-06-06 18:51 ` Richard Jones
@ 2003-06-06 23:08 ` Lauri Alanko
1 sibling, 0 replies; 14+ messages in thread
From: Lauri Alanko @ 2003-06-06 23:08 UTC (permalink / raw)
To: caml-list
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:
>
> let rec read_all_lines chan accum =
> try
> let line = input_line chan in
> read_all_lines chan (line :: accum)
> with
> End_of_file -> List.rev accum
This is a good argument for the alternative exception handling syntax
proposed by in "Exceptional syntax", JFP 11(4):395-410,
<http://research.microsoft.com/~nick/except.ps>. They suggest a form
try x <= e1 in e2 unless E => e3
which acts like "let x = e1 in e2" when e1 causes no exceptions, but
otherwise goes directly to the handler and skips e2 entirely.
So the function above could be written:
let rec read_all_lines chan accum =
try
line <= input_line chan
in
read_all_lines chan (line :: accum)
unless
End_of_file => List.rev accum
It looks almost the same, but here the scope of the handler does _not_
extend over the recursive call, only the binding
Actually, as pointed out by the article, this thing has been suggested
on caml-list before: <http://caml.inria.fr/archives/199912/msg00078.html>.
Lauri Alanko
la@iki.fi
-------------------
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
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Why do input* and readdir throw End_of_file ... annoying!
2003-06-06 18:43 ` Richard Jones
@ 2003-06-07 15:08 ` Eric C. Cooper
2003-06-07 20:27 ` David Brown
2003-06-09 9:31 ` Fabrice Le Fessant
0 siblings, 2 replies; 14+ messages in thread
From: Eric C. Cooper @ 2003-06-07 15:08 UTC (permalink / raw)
To: caml-list
On Fri, Jun 06, 2003 at 07:43:04PM +0100, Richard Jones wrote:
> The problem is that there doesn't seem to be a way to write the
> loop function using readdir. eg:
>
> let rec loop () =
> let filename = readdir dirh in
> match filename with
> | "." -> loop ()
> | ".." -> loop ()
> | filename ->
> let pathname = path ^ "/" ^ filename in
> let stat = lstat pathname in
> let this = if stat.st_kind = S_DIR then
> read_directory pathname
> else
> File pathname in
> this :: loop ()
> in
> try
> Directory (loop ())
> with
> End_of_file -> XXX what?
>
> Because the exception is always raised (it's not an exception at all)
> there's no way to return the result of the call to loop ().
Define your loop to take an accumulator (a list of the results so far):
let rec read_filesystem path =
if (lstat path).st_kind = S_DIR then
Directory (read_directory pathname)
else
File path
and read_directory path =
let dirh = opendir path in
let rec loop entries =
try match readdir dirh with
| "." | ".." -> loop entries
| filename -> loop (read_filesystem filename :: entries)
with End_of_file -> entries
in
let list = loop [] in
closedir dirh;
list
--
Eric C. Cooper e c c @ c m u . e d u
-------------------
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
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Why do input* and readdir throw End_of_file ... annoying!
2003-06-07 15:08 ` Eric C. Cooper
@ 2003-06-07 20:27 ` David Brown
2003-06-07 21:46 ` art yerkes
2003-06-09 15:33 ` Brian Hurt
2003-06-09 9:31 ` Fabrice Le Fessant
1 sibling, 2 replies; 14+ messages in thread
From: David Brown @ 2003-06-07 20:27 UTC (permalink / raw)
To: caml-list
On Sat, Jun 07, 2003 at 11:08:54AM -0400, Eric C. Cooper wrote:
> and read_directory path =
> let dirh = opendir path in
> let rec loop entries =
> try match readdir dirh with
> | "." | ".." -> loop entries
> | filename -> loop (read_filesystem filename :: entries)
> with End_of_file -> entries
> in
> let list = loop [] in
> closedir dirh;
> list
But, this isn't tail recursive, so you might as well not pass the
argument and build up the list upon returning. Is there a way of making
it really tail recursive, while using the exception? It isn't too hard
with a list ref to accumulate the results.
Dave
-------------------
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
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Why do input* and readdir throw End_of_file ... annoying!
2003-06-07 20:27 ` David Brown
@ 2003-06-07 21:46 ` art yerkes
2003-06-09 15:33 ` Brian Hurt
1 sibling, 0 replies; 14+ messages in thread
From: art yerkes @ 2003-06-07 21:46 UTC (permalink / raw)
To: David Brown; +Cc: caml-list
On Sat, 7 Jun 2003 13:27:11 -0700
David Brown <caml-list@davidb.org> wrote:
> On Sat, Jun 07, 2003 at 11:08:54AM -0400, Eric C. Cooper wrote:
>
> > and read_directory path =
> > let dirh = opendir path in
> > let rec loop entries =
> > try match readdir dirh with
> > | "." | ".." -> loop entries
> > | filename -> loop (read_filesystem filename :: entries)
> > with End_of_file -> entries
> > in
> > let list = loop [] in
> > closedir dirh;
> > list
>
> But, this isn't tail recursive, so you might as well not pass the
> argument and build up the list upon returning. Is there a way of making
> it really tail recursive, while using the exception? It isn't too hard
> with a list ref to accumulate the results.
>
> Dave
how about:
open Unix
let read_fs starting_dir =
let rec go_until_exception list_ref f =
list_ref := (f ()) :: !list_ref ; go_until_exception list_ref f
and dirs_ref = ref [] in
let the_dir = opendir starting_dir in
try
go_until_exception dirs_ref (fun () -> readdir the_dir)
with End_of_file -> !dirs_ref
>
> -------------------
> 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
--
`No, you don't understand,' the Knight said, looking a little vexed.
`That's what the name is called. The name really is "The Aged Aged
Man."'
-- Lewis Carroll
-------------------
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
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Why do input* and readdir throw End_of_file ... annoying!
2003-06-07 15:08 ` Eric C. Cooper
2003-06-07 20:27 ` David Brown
@ 2003-06-09 9:31 ` Fabrice Le Fessant
1 sibling, 0 replies; 14+ messages in thread
From: Fabrice Le Fessant @ 2003-06-09 9:31 UTC (permalink / raw)
To: Eric C. Cooper; +Cc: caml-list
> On Fri, Jun 06, 2003 at 07:43:04PM +0100, Richard Jones wrote:
> > The problem is that there doesn't seem to be a way to write the
> > loop function using readdir. eg:
Why don't you use the while ... do ... done loop instead with an
external reference ?
let list = ref [] in
let dir = opendir "......." in
try
while true do
match readdir dir with
"." | ".." -> ()
| filename -> list := filename :: !list
done
with End_of_file -> !list
Recursive functions are elegant to use, but sometimes, it is simpler
to use simple loops instead.
- Fabrice
-------------------
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
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Why do input* and readdir throw End_of_file ... annoying!
2003-06-07 20:27 ` David Brown
2003-06-07 21:46 ` art yerkes
@ 2003-06-09 15:33 ` Brian Hurt
1 sibling, 0 replies; 14+ messages in thread
From: Brian Hurt @ 2003-06-09 15:33 UTC (permalink / raw)
To: David Brown; +Cc: caml-list
On Sat, 7 Jun 2003, David Brown wrote:
> On Sat, Jun 07, 2003 at 11:08:54AM -0400, Eric C. Cooper wrote:
>
> > and read_directory path =
> > let dirh = opendir path in
> > let rec loop entries =
> > try match readdir dirh with
> > | "." | ".." -> loop entries
> > | filename -> loop (read_filesystem filename :: entries)
> > with End_of_file -> entries
> > in
> > let list = loop [] in
> > closedir dirh;
> > list
>
> But, this isn't tail recursive, so you might as well not pass the
> argument and build up the list upon returning. Is there a way of making
> it really tail recursive, while using the exception? It isn't too hard
> with a list ref to accumulate the results.
let read_directory path =
let dirh = opendir path in
let rec loop entries =
let fname, eof = try (readdir dirh), false
with End_of_file -> "", true
in
if eof then List.rev entries else
match fname with
| "." | ".." -> loop entries
| _ -> loop (fname :: entries)
in
loop []
I will also take this opportunity to plug ExtLib. Using ExtLib you can
remove the List.rev call, and do something like:
let read_directory path =
let dirh = opendir path in
let rec f () = try
match readdir dirh with
| "." | ".." -> f()
| s -> s
with End_of_file -> raise No_more_elements
in
ExtList.of_enum (Enum.from f)
Here f is not tail recursive- but it only recurses to get past "." and
".." files, so it'll never go more than 3 levels deep. If it bugs you,
rewrite f in a manner to my first example.
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
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2003-06-09 15:15 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-06-06 17:01 [Caml-list] Why do input* and readdir throw End_of_file ... annoying! Richard Jones
2003-06-06 17:30 ` Michal Moskal
2003-06-06 18:03 ` Ville-Pertti Keinonen
2003-06-06 18:43 ` Richard Jones
2003-06-07 15:08 ` Eric C. Cooper
2003-06-07 20:27 ` David Brown
2003-06-07 21:46 ` art yerkes
2003-06-09 15:33 ` Brian Hurt
2003-06-09 9:31 ` Fabrice Le Fessant
2003-06-06 18:49 ` Brian Hurt
2003-06-06 18:51 ` Richard Jones
2003-06-06 19:09 ` [Caml-list] " Alan Post
2003-06-06 19:44 ` [Caml-list] " Brian Hurt
2003-06-06 23:08 ` Lauri Alanko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox