[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
| Date: | -- (:) |
| From: | Zheng Li <zheng_li@u...> |
| Subject: | Re: Stricter version of #use ? |
Hi John, On 3/25/2009 1:14 AM, Harrison, John R wrote: > So with my "root.ml" and "branch.ml" files from the first message, it > all works exactly as I wanted, a nice early failure with a clear > "traceback": > > # #use "root.ml";; > val x : int = 1 > val u : int = 3 > Exception: Failure "X". > Error in included file branch.ml > # x;; > - : int = 1 > # u;; > - : int = 3 > > Yet if I replace the line > > #use "branch.ml";; > > in "root.ml" with what I supposed would be equivalent: > > use_file "branch.ml";; > > then the exception propagates out and I get the "rollback" that > I wanted to avoid: > > # #use "root.ml";; > val x : int = 1 > val u : int = 3 > Exception: Failure "X". > Error in included file branch.ml > Exception: Pervasives.Exit. > # x;; > - : int = 1 > # u;; > Unbound value u > > Any idea why that should be? The execution difference between a toplevel phrase like "use_file xxx" and a toplevel directive like "#use xxx" is subtle. The current toplevel implementation always execute a toplevel phrase in a protected environment, i.e. the execution effect of a single toplevel phrase is always all-or-nothing. And this is, AFAIK, hard-wired in the code and I don't know how to tweak it without modifying the toplevel source. On the other hand, the toplevel won't protect the execution of a directive, rather it relies on the directives to protect themselves --- that's why we can still do some little trick without modifying the toplevel source. So in the end, you can't partly keep the execution effect of a toplevel phrase like "use_file xxx". Moreover, I can't see how we can avoid this (if we intend to use "use_file" as a function rather than a directive), no matter how we define "use_file". If the "use_file" fails upon some inside errors, the whole effect of its execution will be aborted due to the protected environment; if we catch the errors ourselves, i.e. the whole execution still returns successfully despite the inside error, then the rest of the code (below "use_file xxx") will continue to run. The only solution (without modifying toplevel) is to define "use_file" as a function always succeeds and returns a flag telling whether the execution is all successful. Then it will be the responsibility of programmers to decide to abort or continue or reset. Something like: val use_file: string -> (unit -> unit) option it returns either None on full success or Some reset to let the programmers choose whether to abort (raise Exit) or (reset ()). Regards -- Zheng