Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
From: skaller <skaller@users.sourceforge.net>
To: caml-list <caml-list@inria.fr>
Subject: RE: [Caml-list] Checking for eof
Date: 27 Dec 2004 11:14:51 +1100	[thread overview]
Message-ID: <1104106491.18148.232.camel@pelican.wigram> (raw)
In-Reply-To: <5DCA48FADB33FF4D8C32A164DF24F2B002374E6E@EUR-MSG-03.europe.corp.microsoft.com>

On Mon, 2004-12-27 at 02:25, Don Syme wrote:

> An OCaml or F# version of their construct might be 
>   "let try <bindings> 
>    in <expr> 
>    with <matching>"

> Another possibility might be 
> 
>   "let try <bindings> 
>    with <matching>
>    in <expr> "
> 

let readfile chan = 
  let x = ref [] in 
  try while true do x:= input_line chan :: !x done
  with End_of_file -> List.rev !x

is only 4 lines :)

However, this is a bad use of exceptions, IMHO,
since End_of_file isn't an error, and when thrown
should never propagate far. With an option type instead:

let readfile chan =
  let rec loop rlst = 
    match input_line chan with
    | None -> List.rev rlst
    | Some x -> loop (x::rlst)
  in loop []

is 6 lines and clearly tailrec.

---------------------

Here is what Felix does:

proc f() {
  g handler;

  noreturn proc handler (x:int) { 
    print "Error "; print x; endl;
    goto endoff;
  }

endoff:>
}

Here, the handler is *passed* to the routine g,
which calls it in event of an exceptional situation,
the handler code then 'throws' by doing a non-local goto.
(This unwinds the stack).

This technique has a couple of advantages,
the most important one being that it is *impossible*
to fail to catch an exception. If code can 'throw'
an exception, the type system ensures you pass it
a handler.

There is also no problem with creating 'exception types',
handlers are just ordinary procedures.

Finally an actual 'pragmatic' test on Alioth Shoothout
had the Felix version of the test banned because it
totally wiped out all other solutions on performance.
I don't mean it was a bit faster -- it was orders
of magnitude faster.

The reason is the test was too simple, and the optimiser
managed to reduce the whole test to a flat loop,
the goto became local (local gotos in Felix become gotos in C).

Optimisation of dynamic exceptions is very hard.
This is because the raise and catch points are entirely
decoupled statically: the coupling is entirely dynamic
based on RTTI (even in Ocaml).

The Felix technique on the other hand combines
static scoping with dynamic argument passing
in the *usual* way.

It is much easier to reason about, provided
the goto target is sensibly placed.

It remains to encapsulate this technique in a nicer
syntax than 'goto' for example something like:


proc f() {
  exception handler (x:int) { 
    print "Error "; print x; endl;
  }

  g handler;
}

Note the handler of course doesn't have to
be passed in the case it would be in scope anyhow,
in which case the same syntax can be used to
obtain fully static exception handling.

[Felix doesn't have a way to put 'noreturn' in the typing,
which would be needed to be sure when you 'throw' an
exception it doesn't return]

In particular, the 'analogue' of dynamic exception
handling is obtained by storing the handler in a
global variable, which means anyone can jump to it.
This is the same as having an exception represented
by a globally agreed on 'exception type'.

What happens if the handler stack frame is already
popped? Well, in Felix the handler runs fine,
and the goto works (the stack frames are all heap
allocated and garbage collected) -- however the
falling off the end of the enclosing dead procedure
terminates the program (because the return address
is reset to NULL on returning, so the GC can
collect the caller)

If this sounds bad -- this is exactly what an 
uncaught exception does.

And now you can see, using the Felix technique
as a model, some indication why dynamic EH is so bad. 
It is equivalent to using a global variable for
something that *should* be local.

The difference is that 'variable' in Felix can
be localised as required, and the localisation
is then supported by the type system.

This technique can of course by used in Ocaml.
Although there is no 'goto' you can emulate it
with exceptions (LOL)

exception goto;
let f () =
  let handler i = 
    print_endline ("Error " ^ string_of_int i);
    raise goto;
  in
  try g handler
  with goto -> ()

It may be possible to leverage local modules to
provide some way to localise the exception
and guarrantee statically it can't escape
(possibly allowing Ocaml to optimise..?)


-- 
John Skaller, mailto:skaller@users.sf.net
voice: 061-2-9660-0850, 
snail: PO BOX 401 Glebe NSW 2037 Australia
Checkout the Felix programming language http://felix.sf.net




  reply	other threads:[~2004-12-27  0:14 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-12-26 15:25 Don Syme
2004-12-27  0:14 ` skaller [this message]
  -- strict thread matches above, loose matches on Subject: below --
2004-12-26  1:12 romildo
2004-12-26  1:58 ` [Caml-list] " briand
2004-12-26 13:09   ` Nicolas George
2004-12-27 20:23     ` Martin Jambon

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=1104106491.18148.232.camel@pelican.wigram \
    --to=skaller@users.sourceforge.net \
    --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