Version française
Home     About     Download     Resources     Contact us    
Browse thread
Stricter version of #use ?
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ 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