Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
From: CREGUT Pierre FTRD/DTL/LAN <pierre.cregut@rd.francetelecom.fr>
To: caml-list@inria.fr
Subject: Re: unwind-protect?
Date: Fri, 17 Nov 2000 14:54:07 +0100	[thread overview]
Message-ID: <20001117145407.A24233@lat4149.lannion.cnet.fr> (raw)
In-Reply-To: <200011171228.NAA21785@pauillac.inria.fr>; from Pierre.Weis@inria.fr on ven, nov 17, 2000 at 01:28:46 +0100

Pierre's solution repeat chdir which is often the long part of the code.
I like to use the following constructs (I am looking for smarter constructs.
I am also looking for a standard way of doing it that would go in the
standard library) :

  type 'a result = Normal of 'a | Exception of exn
  let catch f a = try Normal (f a) with e -> Exception e
  let throw = function Normal a -> a | Exception e -> raise e
  let with_fallback v f fallback = 
    match v with Normal a -> f a | Exception e -> fallback e

There are some contexts where it is as ubiquitous as the 'a option type.
For example, RPC on cin : 

  let cout, msg = sync(receive cin) in sync(send (catch f msg))

On the other side you will find :

  let channel = new_channel () in
  sync(send (channel,msg)); throw (sync (receive channel))  

In the chdir problem (or if you use any kind of lock construct) you can write :

  chdir ...;
  let r = catch (f a);
  chdir ...;
  throw r

The with_fallback function can be used to simulate the so much missing

   trylet .... in .... with ...

capturing only errors in the let part.

Pierre


                            ANNEX
                            =====

i am not convinced that with_fallback is the definitive answer for a fine 
grained control of exceptions.  To complete a previous post, I would prefer a 
new "context" construct

let complex_function .... =
  try
    let v = context c1 f x1 x2 ... in
    ....
    g (context c2 h y1 y2 ...) z1 z2 ...
    ...
  with
    E1 in c1 -> ....
  | E2 in c2 -> ....
  | E -> ....

Combined with a tool like ocamlexc, you can  
- have readable code that separates exceptional cases from the regular
  treatment.
- be sure that all your exceptions are trapped
- be convinced that your error handling code is trapping the right exception
  not another one that happened to have the same name (typical of Not_found
  exception handlers). 
(Note that the "looped approximation' of recursive datatype by ocamlexc could
limit the power of the analysis as we use an exception containing another
exception.)

Here is a crude prototype in CAMLP4 (lists are not needed, but you must
remember which context is embedded in which one. There are also issues
with tail recursion that can be broken.

********** exc.ml *************
exception Located of exn * string list
 
let extract = function Located(e,l) -> e,l | e -> e,[]
 
let present exc l = List.mem exc l      

**********excemption.ml*************
open Pcaml
open MLast

let match_case = Grammar.Entry.find expr "match_case"
let try_case = Grammar.Entry.create Pcaml.gram "try_case"

DELETE_RULE
  expr: "try"; expr; "with"; OPT "|"; LIST1 match_case SEP "|"
END

EXTEND
  expr :
   [ [ "try"; x = expr; "with"; OPT "|"; l = LIST1 try_case SEP "|" ->
        let l' = l @ [(<:patt<_>>,None,<:expr<raise _exc_>>)] in
        <:expr< try $x$ with [ _exc_ ->
            let (_e_,_loc_) = Exc.extract _exc_ in
            match _e_ with [ $list:l'$ ] ] >>
    | "context"; name =  UIDENT; e = expr ->
        <:expr<
           try $e$ with
           [  Exc.Located(e,l) -> raise (Exc.Located(e, [ $str:name$ :: l]))
           | e -> raise (Exc.Located(e,[$str:name$]))] >> ]]
  ;
  try_case :
    [[ p = patt; aso = OPT [ "as"; p = patt -> p ];
       at_location = OPT ["in"; location = UIDENT -> location];
       w_opt = OPT [ "when"; e = expr -> e ]; "->"; e = expr ->
          let p_with_as =
            match aso with
              Some as_pat -> <:patt< ($p$ as $as_pat$) >>
            | _ -> p in
          let w_with_at =
            begin match w_opt,at_location with
            | Some w,Some lc -> Some(<:expr<($w$) && (Exc.present $str:lc$ _loc_)>>)
            | None,Some lc -> Some (<:expr<Exc.present $str:lc$ _loc_>>)
            | _,None -> w_opt
            end in
          (p_with_as, w_with_at, e) ]]
  ;
END  


-- 
Pierre Cregut - pierre.cregut@rd.francetelecom.fr - +33 2 96 05 16 28
FTR&D - DTL/MSV - 2 avenue Pierre Marzin - 22307 Lannion Cedex - France



  reply	other threads:[~2000-11-19 14:50 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2000-11-17  6:23 unwind-protect? Colin Walters
2000-11-17 12:28 ` unwind-protect? Pierre Weis
2000-11-17 13:54   ` CREGUT Pierre FTRD/DTL/LAN [this message]
2000-11-17 14:01 unwind-protect? Damien Doligez
2000-11-21  9:36 ` unwind-protect? Pierre Weis
2000-11-17 14:37 unwind-protect? David McClain

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=20001117145407.A24233@lat4149.lannion.cnet.fr \
    --to=pierre.cregut@rd.francetelecom.fr \
    --cc=caml-list@inria.fr \
    /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