caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: oleg@pobox.com
To: caml-list@inria.fr
Subject: Resumable exceptions in plain OCaml
Date: Wed, 14 Jun 2006 15:54:03 -0700 (PDT)	[thread overview]
Message-ID: <20060614225403.69F73AC97@Adric.metnet.fnmoc.navy.mil> (raw)


Resumable exceptions are the strict generalization of regular exceptions,
which lets the exception raising form return a value and so the
computation may continue. It's the exception handler that decides
either to abort the exceptional computation or to resume it with a
particular value. Resumable exceptions are made popular by Common
Lisp, where they are widely used: http://lambda-the-ultimate.org/node/1544

We show a conservative and elementary implementation of resumable
exceptions in OCaml: the implementation is a self-contained 100% pure
OCaml library; makes no changes to the OCaml system; supports the
existing style of defining exceptions; is compatible with the ordinary
exceptions; works in byte- or natively-compiled code; uses the most
basic facilities of ML and so can easily be translated to SML.

We impose no extra restrictions on the resumable exception raising and
handling forms. Like with ordinary exceptions, resumable ones may
encapsulate values of arbitrary types; the same exception handler may
process exceptions of many types -- and send resumption replies of
many types. The raise form may appear within the guarded code at many
places; different raise forms may resume with values of different
types. Furthermore, resumable exceptions are declared just like the
ordinary ones, with the `exception' keyword. If the resumable
exception handler never resumes, resumable exceptions act and feel
precisely as the regular ones.

The control aspect of resumable exceptions is quite trivial: as first
pointed out by Luc Moreau (HOSC1998), invoking a resumable expression
is sort of a regular function call, where the name of the function,
the handler, is obtained via dynamic binding. It is the typing aspect
of resumable exceptions -- imposing no restrictions on how and when
exceptions can be raised and resumed -- that took most of the
work. The resulting implementation involves less than common ways of
invoking functions and passing their results.

The implementation and illustration code is available at
	http://pobox.com/~oleg/ftp/ML/resumable.ml

The following is an excerpt from the above file, illustrating
resumable exceptions. As regular exceptions, resumable exceptions must
be declared, with the ordinary keyword 'exception'. A resumable
exception amounts to two (or more) ordinary exceptions. The first is
what used to raise the (resumable) exception.  The second is to
encapsulate the returned result. The function [rhandle] is equivalent to
the [try] form; it receives the exception handler and the thunk. The
function [rraise : exn -> (exn -> 'a) -> 'a] raises the resumable
exception. Its second argument receives the resumable exception,
should unpack it and return the resumption result, with which to
continue the computation.


(* Declare the first resumable exception. It has resumptions of two types *)
exception Foo of int
exception Foo_r1 of bool
exception Foo_r2 of string

(* Declare the second resumable exception *)
exception Bar of char
exception Bar_r of int

let handler v = try raise v with
  | Foo x -> Printf.printf "Got Foo of %d\n" x; 
      if x < 100 then resume (Foo_r1 (x < 4)) else resume (Foo_r2 "xxx")
  | Bar c -> Printf.printf "Got Bar of %c\n" c;
      if c < 'E' then resume (Bar_r (int_of_char c + 1))
      else 42.0                                          (* aborting *)

let () =
  let r = rhandle handler 
   (fun () ->
     for i = 1 to 5 do
       let v = rraise (Foo i) (fun e -> try raise e with Foo_r1 x -> x) in
       let () = Printf.printf "Resumed Foo1 with %b\n" v in
       let v = rraise (Foo (100 +i)) (fun e -> try raise e with Foo_r2 x -> x)
       in Printf.printf "Resumed Foo2 with %s\n" v
     done;
     for i = 65 to 100 do
       let v = rraise (Bar (char_of_int i)) 
               (fun e -> try raise e with Bar_r x -> x)
       in Printf.printf "Resumed Bar with %d\n" v
     done;
     assert false
   ) in
  Printf.printf "\nFinal result %g\n" r
;;


             reply	other threads:[~2006-06-14 23:02 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-06-14 22:54 oleg [this message]
2006-06-14 23:46 ` [Caml-list] " Erik de Castro Lopo
2006-06-16 21:33 ` Christophe Raffalli
2006-06-16 21:41   ` Christophe Raffalli
2006-06-17  7:45   ` oleg
2006-06-18  9:01 ` Dmitry Bely
2006-06-19 21:40   ` oleg

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=20060614225403.69F73AC97@Adric.metnet.fnmoc.navy.mil \
    --to=oleg@pobox.com \
    --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;
as well as URLs for NNTP newsgroup(s).