[
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: | Alain Frisch <Alain.Frisch@i...> |
| Subject: | Re: [Caml-list] try .. finally .. |
Jon Harrop wrote:
> (* The function that returns unique identifiers *)
> let new_id =
> let counter = ref 0 in
> fun () ->
> incr counter;
> "__finally" ^ string_of_int !counter
>
> (* The function that converts our syntax into a single OCaml expression,
> i.e. an "expr" node of the syntax tree *)
> let expand loc e1 e2 =
> let id = new_id () in
> let id_patt = <:patt< $lid:id$ >> in
> let id_expr = <:expr< $lid:id$ >> in
> <:expr<
> let $id_patt$ =
> try do { $e1$; None }
> with [ exn -> Some exn ] in
> do { $e2$;
> match $id_expr$ with
> [ None -> ()
> | Some exn -> raise exn ] }
> >>
Note that this implementation breaks tail positions of e2 (when no
exception is raised in e1, one might want to preserve tail-calls in e2
-- or not)...
> let unwind_protect f g =
> let fin = ref false in
> try
> let x = f () in
> fin := true;
> g();
> x
> with exn when !fin ->
> g();
> raise exn
and this one too, and you want (not !fin) instead of !fin.
Why not:
let unwind_protect f g =
match (try f (); None with exn -> Some exn) with
| None -> g ()
| Some exn -> g (); raise exn
?
In the original version, I believe one could always use the same
identifier, without any extra conflicts. In the second version, you also
need to reserve one identifier (unwind_protect); of course, you can
inline its definition.
> Is this a general observation about macros?
If you mean that regular OCaml abstractions are better behaved w.r.t. to
the binding of identifiers than Camlp4 macros, I'd say the answer is yes.
-- Alain