caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: John Prevost <visigoth@cs.cmu.edu>
To: Oliver Bandel <oliver@first.in-berlin.de>
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] Stack Overflow... (recursion in try-statement)
Date: 24 Apr 2002 00:10:47 -0400	[thread overview]
Message-ID: <86adrtvirc.fsf@laurelin.dementia.org> (raw)
In-Reply-To: <Pine.LNX.3.95.1020423233831.10014A-100000@first.in-berlin.de>

>>>>> "ob" == Oliver Bandel <oliver@first.in-berlin.de> writes:

    ob> Hello, why does an stack overflow-error occur here?

let rec traversedir dir =
          try ( [Unix.readdir dir] @ traversedir dir ) with
          End_of_file -> [];;

    ob> I have not tried it with very deep directories, so I did not
    ob> expect such an error...

    ob> What is the problem here?

The problem is that when you write:

[Unix.readdir dir] @ traversedir dir

the recursive call happens first.  Say you have a directory with only
one entry in it:

traversedir dir
=>
try ( [Unix.readdir dir] @ traversedir dir ) with
End_of_file -> []
=>
try ( [Unix.readdir dir] @
  (try [Unix.readdir dir] ...) ) with
End_of_file -> []

and so on.  Hence, readdir is never actually called.

Note that it is *not* safe to turn this around in order to fix things,
since the order of evaluation is not guaranteed.  In fact, unless it
has changed, the above will fail in bytecode but not native code, and
the reverse will work in bytecode but fail on native.  The appropriate
way to do it is:

let rec traversedir dir =
  try
    let entry = Unix.readdir dir in
    [entry] @ traversedir dir
  with End_of_file -> []

This has its own problems, since it's not tail recursive, but it will
not go into an endless loop.  A better formulation is:

let traversedir dir =
  let rec loop l =
    match (try Some (Unix.readdir dir) with End_of_file -> None) with
      | Some ent -> loop (ent :: l)
      | None     -> l
  in loop []

Whether to go this far and be tail recursive is up to you, of course.
Note that if you are going to go for tail recursion, it's important to
make sure the try is not around the tail call, since exception
handling blocks tail calls.

Finally, the following could be useful to you:

let mapdir f accum dir =
  let rec loop accum =
    match (try Some (Unix.readdir dir) with End_of_file -> None) with
      | Some ent -> f ent accum
      | None     -> accum
  in loop accum

let cons x y = x :: y
let traversedir = mapdir cons []

John.
-------------------
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


  parent reply	other threads:[~2002-04-24 10:46 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-04-23 21:48 Oliver Bandel
2002-04-23 22:23 ` Will Benton
2002-04-23 22:50 ` Oliver Bandel
2002-04-23 23:25   ` John Prevost
2002-05-21 18:34     ` [Caml-list] Is CVS version of ocaml faster? John Max Skaller
2002-05-22  3:03       ` Jacques Garrigue
2002-05-22 16:29         ` John Max Skaller
2002-06-30 17:25     ` [Caml-list] ocamllex -- ambiguous regex John Max Skaller
2002-07-01 11:45       ` Xavier Leroy
2002-06-30 17:27     ` [Caml-list] Manual broken -- set John Max Skaller
2002-04-24  1:01 ` [Caml-list] Stack Overflow... (recursion in try-statement) Warp
2002-04-24 13:22   ` Oliver Bandel
2002-04-24  4:10 ` John Prevost [this message]
2002-04-24  4:52 ` Alan Schmitt
2002-04-24  5:31   ` Charles Martin
2002-04-24 13:25   ` Oliver Bandel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=86adrtvirc.fsf@laurelin.dementia.org \
    --to=visigoth@cs.cmu.edu \
    --cc=caml-list@inria.fr \
    --cc=oliver@first.in-berlin.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).