<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>exceptional-situation &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://en.wordpress.com/tag/exceptional-situation/</link>
	<description>Feed of posts on WordPress.com tagged "exceptional-situation"</description>
	<pubDate>Fri, 04 Dec 2009 19:24:16 +0000</pubDate>

	<generator>http://en.wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[Improving exception-management in OCaml]]></title>
<link>http://dutherenverseauborddelatable.wordpress.com/2008/07/02/improving-exception-management-in-ocaml/</link>
<pubDate>Wed, 02 Jul 2008 14:46:28 +0000</pubDate>
<dc:creator>yoric</dc:creator>
<guid>http://dutherenverseauborddelatable.wordpress.com/2008/07/02/improving-exception-management-in-ocaml/</guid>
<description><![CDATA[Short version Catch me if you can is a small library for OCaml 3.10. The latest release is version 0]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><h2 style="text-align:justify;">Short version</h2>
<p style="text-align:justify;">Catch me if you can is a small library for OCaml 3.10. The latest release is version 0.2, which you may find <a href="http://www.univ-orleans.fr/lifo/Members/David.Teller/software/exceptions/catch_0_2.tgz">here</a>. This library improves management of errors in OCaml. It is released under the LGPL licence. It has been written by David Teller, Arnaud Spiwack, Till Varoquaux and Gabriel Scherer.</p>
<p><!--more--></p>
<hr />
<h2><strong>Long version<br />
</strong></h2>
<p align="justify">As all languages of the ML family &#8212; and most modern languages indeed &#8212; OCaml permits the management of exceptional situations using <em>exceptions</em>. This mechanism lets programmer register protected sections of code, as well as <em>exception handlers</em> to handle any exception which may be <em>raised</em> during the execution of a protected section. Whenever an exception is <em>raised</em>, the protected section of code is immediately stopped and the corresponding exception handler is executed instead. In addition, exceptions may convey some information regarding the nature of the exceptional circumstance.</p>
<p align="justify">In OCaml, the mechanism is fast, it&#8217;s convenient and it&#8217;s type-safe, much like the rest of the language (barring any type-unsafe interaction with C). However, a few things are missing. If we consider the rest of the language, exceptions are both heavyweight and clumsy: each exception must be declared before being used and there&#8217;s no way to introduce a polymorphic type parameter in the exception. In addition, languages such as Java offer to important features missing in OCaml: automatic case coverage and exception hierarchies. While <a href="http://caml.inria.fr/pub/old_caml_site/ocamlexc/ocamlexc.htm">a nice tool</a> exists  to provide case coverage for exceptions in OCaml, this tool is complex and  unfortunately unmaintained.</p>
<p align="justify"><em>Catch me if you can</em> offers an alternative mechanism, comparable to ML exceptions, to handle errors. In comparison with OCaml&#8217;s native exception mechanism, this library adds:</p>
<ul>
<li>automatic inference of exceptions (i.e. no need to declare your exceptions, unless you want to)</li>
<li>more flexible exceptions (i.e. exceptions may have polymorphic type parameters, constraints, etc.)</li>
<li>hierarchies (i.e. an IOException is a sub-case of Exception and a super-case of NetworkException)</li>
<li>case coverage (i.e. the compiler can tell you if you forgot a case or sometimes if you wrote useless ones)</li>
<li>conditional success handlers (i.e. do something with the result in case of success)</li>
<li>conditional success-and-failure handlers (i.e. &#8220;finally&#8221;).</li>
</ul>
<p style="text-align:justify;">To attain this, we replace the mechanism of exceptions by an error monad, we replace exception constructors with polymorphic variants and we introduce a dose of syntactic sugar.</p>
<hr />
<h2>Examples</h2>
<h3>Expression evaluator</h3>
<p>Let&#8217;s write a simple expression evaluator for the following set of expressions:</p>
<pre class="brush: python;">
type expr =
  &amp;#124; Value of float
  &amp;#124; Div     of expr * expr
  &amp;#124; Add    of expr * expr
  &amp;#124; Mult   of expr * expr
  &amp;#124; Subs  of expr * expr
</pre>
<p>These may be evaluated using the following function:</p>
<pre class="brush: python;">
let rec eval = function
 &amp;#124; Value x    -&gt; x
 &amp;#124; Add (x,y) -&gt; eval x +. eval y
 &amp;#124; Mult(x,y)  -&gt; eval x *. eval y
 &amp;#124; Div(x,y)   -&gt; eval x /. eval y
 &amp;#124; Subs(x,y) -&gt; eval x -. eval y
</pre>
<p style="text-align:justify;">Of course, this function is bound to fail in case of division by zero. While this is expected, there is nothing in the source code &#8212; much less in the type of the function &#8212; to let us know which exception will be raised in case of division by zero.</p>
<p>An alternative would be to add manual error checking, as follows:</p>
<pre class="brush: python;">
type ('a, 'b) result =
 &amp;#124; Ok of 'a
 &amp;#124; Error of 'b

let rec eval = function
 &amp;#124; Value x    -&gt; OK x
 &amp;#124; Add (x,y) -&gt; (match eval x with
                      &amp;#124; Error e -&gt; Error e
                      &amp;#124; Ok x' -&gt;  match eval y with
                               &amp;#124; Error e -&gt; Error e
                               &amp;#124; Ok y'    -&gt; Ok (x' +. y'))
 &amp;#124; Mult (x,y) -&gt; (match eval x with
                      &amp;#124; Error e -&gt; Error e
                      &amp;#124; Ok x' -&gt;  match eval y with
                               &amp;#124; Error e -&gt; Error e
                               &amp;#124; Ok y'    -&gt; Ok (x' *. y'))
 &amp;#124; Div (x,y) -&gt; (match eval x with
                      &amp;#124; Error e -&gt; Error e
                      &amp;#124; Ok x' -&gt;  match eval y with
                               &amp;#124; Error e -&gt; Error e
                               &amp;#124; Ok y'    -&gt; if y' = 0. then Error &quot;Division by zero&quot;
                                                else              Ok (x' /. y'))
 &amp;#124; Subs (x,y) -&gt; (match eval x with
                      &amp;#124; Error e -&gt; Error e
                      &amp;#124; Ok x' -&gt;  match eval y with
                               &amp;#124; Error e -&gt; Error e
                               &amp;#124; Ok y'    -&gt; Ok (x' -. y'))
(*eval : expr -&gt; (float, string) result*)
</pre>
<p style="text-align:justify;">After this transformation, the type of the exception appears in the type of <code>eval</code> &#8212; here, we used strings, but anything else would have been fine. Of course, the downside is that this is unreadable. Well, what about the following ?</p>
<pre class="brush: python;">
let rec eval = function
 &amp;#124; Value x    -&gt; return x
 &amp;#124; Add (x,y) -&gt; perform with module Error
                        x' &lt;-- eval x;
                        y' &lt;-- eval y;
                        return (x' +. y')
 &amp;#124; Mult (x,y) -&gt; perform with module Error
                        x' &lt;-- eval x;
                        y' &lt;-- eval y;
                        return (x' *. y')
 &amp;#124; Div (x,y) -&gt; perform with module Error
                        x' &lt;-- eval x;
                        y' &lt;-- eval y;
                        if y'=0. then throw &quot;Division by zero&quot;
                        else            return (x' /. y')
 &amp;#124; Subs (x,y) -&gt; perform with module Error
                        x' &lt;-- eval x;
                        y' &lt;-- eval y;
                        return (x' -. y')
(*eval : expr -&gt; (float, string) result*)
</pre>
<p style="text-align:justify;">This extract uses [our customized version of] Pa_monad (included in the package), which brings syntactic support for monads. While this is more verbose than the original version, it&#8217;s also safer, insofar as we can guarantee that exceptions won&#8217;t remain uncaught.</p>
<p>Still too long? Then what about using the appropriate operators?</p>
<pre class="brush: python;">
open Error.Operators
let rec eval = function
 &amp;#124; Value x    -&gt; x
 &amp;#124; Add (x,y) -&gt; eval x +. eval y
 &amp;#124; Mult(x,y) -&gt; eval x *. eval y
 &amp;#124; Div(x,y)   -&gt; eval x /. eval y
 &amp;#124; Subs(x,y) -&gt; eval x -. eval y
</pre>
<p>Except for the module opening, that&#8217;s the same thing as our first listing. Just with the added safety.</p>
<h3>Throwing, catching and hierarchies</h3>
<p>By the way, the type of the result is</p>
<pre class="brush: python;">
(*eval : expr -&gt; (float, [&gt; `Arithmetic of (unit, [&gt; `Div_by_zero of (unit, _) exc ]) exc ]) result*)
</pre>
<p>That is, eval may either succeed and return a float or fail and return an arithmetic exception, which also turns out to be a division by zero. That&#8217;s classes of exceptions.</p>
<p>With our syntactic sugar, raising such an exception is done by</p>
<pre class="brush: python;">
throw (exception Arithmetic (); Div_by_zero ())
</pre>
<p style="text-align:justify;">Note that we could have put some content instead of <code>()</code>. Note that exceptions are typed as they appear in the code and don&#8217;t need to be declared (if you wonder, polymorphic variants are involved in this).</p>
<p>Of course, various kinds of exceptions may be combined, as in the following extract:</p>
<pre class="brush: python;">
match ... with
&amp;#124; 1 -&gt; throw (exception Arithmetic (); Div_by_zero ())
&amp;#124; 2 -&gt; throw (exception Arithmetic (); Overflow &quot;by gosh !&quot;)
&amp;#124; 3 -&gt; throw (exception IO file_descr)
&amp;#124; ...
(*
('a, [&gt; `Arithmetic of (unit, [&gt; `Div_by_zero of (unit, _) exc
                                     &amp;#124;   `Overflow of (string, _)   exc]) exc
     &amp;#124;   `IO of (int, [`&gt; ]) exc ]) result*)
*)
</pre>
<p>While the type of the expression is difficult to read, catching is easy</p>
<pre class="brush: python;">
attempt ... with
 &amp;#124; val s -&gt; (*success*)
 &amp;#124; Arithmetic (); Div_by_zero () -&gt; (*Division by zero*)
 &amp;#124; Arithmetic (); _                   -&gt; (*Other arithmetic*)
 &amp;#124; IO _                                  -&gt; (*Some IO stuff *)
 &amp;#124; finally _                             -&gt; (*Don't forget to close the door*)
</pre>
<p>This extract introduces three keywords:</p>
<ul>
<li><code>attempt</code> is our replacement for <code>try</code></li>
<li><code>val</code> is used to pattern-match against the result of a successful evaluation</li>
<li><code>finally</code> is used to pattern-match against the final result, whether this result was obtained after a successful evaluation or after an exception was raised and handled.</li>
</ul>
<h3>Unbreaking tail-recursion</h3>
<p>The following extract is wrong:</p>
<pre class="brush: python;">
let line_count filename =
  let rec loop file count =
  try
    ignore (input_line file);
    loop file (count + 1)
  with
    End_of_file -&gt; count
  in
    loop (open_file filename) 0
</pre>
<p align="justify">Don&#8217;t get me wrong, it will compile and run. The problem is that it&#8217;s not tail-recursive. In other words, it will be much slower and much more memory-consuming than if exceptions had been ignored. Why ? Because exception End_of_file may have been raised from the next call to loop, so the recursive call cannot be optimized into a non-recursive call. Of course, exceptions can&#8217;t be ignored in this extract, as they are required to determine when to stop reading the file. Now, a simple transformation would make the problem go away :</p>
<pre class="brush: python;">
let line_count filename =
  let rec loop file count =
    let should_continue =
    try
      ignore (input_line file);
      true
    with End_of_file -&gt; false
  in
    if should_continue then loop file (count + 1)
    else                    count
  in
    loop (open_file filename) 0
</pre>
<p style="text-align:justify;">Well, the transformation is simple, but it&#8217;s annoying and hard to read. What&#8217;s even more annoying is that it&#8217;s quite common. With Catch me if you can, we would rather write the following:</p>
<pre class="brush: python;">
let input_line2 x = Error.legacy input_line x

let line_count filename =
  let rec loop file count =
    attempt input_line2 file with
      &amp;#124; val _ -&gt; loop file (count + 1)
      &amp;#124; _     -&gt; count
  in
  loop (open_file filename) 0
</pre>
<p style="text-align:justify;">In this extract, legacy is a simple manner of wrapping an existing, one-argument, function and convert it to our new exception style. It&#8217;s not quite as good as wrapping the function manually and giving it an actual exception, but it&#8217;s better than nothing.</p>
<p align="justify">All in all, the resulting function line_count is shorter, easier to read, takes less memory and is also faster than the original.</p>
<h2>What about performance?</h2>
<p style="text-align:justify;">Now, that&#8217;s a complex question. Short answer: there&#8217;s an acceptable performance loss. False short answer: we wrote a <a href="http://www.univ-orleans.fr/lifo/Members/David.Teller/publications/ml2008.pdf">paper</a> on that subject.</p>
</div>]]></content:encoded>
</item>

</channel>
</rss>
