Re: Une idee pour etendre le mecanisme d'exceptions.

Pierre Weis (weis@pauillac.inria.fr)
Tue, 14 Nov 1995 17:39:46 +0100 (MET)

From: Pierre Weis <weis@pauillac.inria.fr>
Message-Id: <199511141639.RAA25471@pauillac.inria.fr>
Subject: Re: Une idee pour etendre le mecanisme d'exceptions.
To: raffalli@cs.chalmers.se (Christophe Raffalli)
Date: Tue, 14 Nov 1995 17:39:46 +0100 (MET)
In-Reply-To: <199511141335.OAA29395@lips.cs.chalmers.se> from "Christophe Raffalli" at Nov 14, 95 02:35:13 pm

> It will be interesting to provide a function
> add_to_handler : (unit -> 'a) -> ('a -> unit) -> unit
> such that, if add_to_handler save restore; is evaluated then
> any piece of code
> try
> expr
> with
> e -> expr'
> is equivalent to:
> let save_state = save () in
> try
> expr
> with
> e -> restore save_state; expr'
>
> (evidently, we need to be able to handle several "add_to_handler").
>
> add_to_handler might be a directive #add_to_handler instead of a
> function ?

In fact the general concept here is the ability to use ``dynamic
binding'' instead of the default regime of Caml which is ``static
binding'' (or lexical binding, or $\lambda$-calculus binding regime).

Dynamic binding, is characterized by the fact that you can use (more
exactly cite) a variable before its definition, and that the value of
a variable depends on the computation: it is the last {\em
dynamically} encountered binding for the variable that gives the
value.

Let's give an example:

let x = 1;;

let f = function y -> y + x;;

In regular Caml:

let x = 2 in f 3;; gives 4
(the outer let x = 2 binding has no effect in the body of f:
the value of x in the body of f is still 1)

Now, if we imagine that Caml obeys dynamic binding

let x = 2 in f 3;; => 5
(the outer let x = 2 binding is the last encountered binding for x,
hence the value of x in the body of f becomes 2)

As in static binding, and since the binding of x is local, the
toplevel value of x reverts to 1 after the evaluation of the phrase.

You may argue that this semantics is awkward. Yes in general, but
unfortunately this is sometimes mandatory. Thus, for these special
circumstances, Caml programmers have developped standard tricks to
circumvert the static binding discipline of Caml.

The usual encoding of dynamic binding in Caml is not surprising:
all dynamic variables are defined as references (your state variables)
instead of regular variables. We affect their value just before
calling the functions, and restore them back after the calls, as suggested by:

let x = ref 1;;

let f = function y -> y + !x;;

let saved_x = !x in
let result = x := 2; f 3 in
x := saved_x;
result;;

This does not respect the semantics of dynamic binding completely,
since the old value of x is not restored when the function called raises
an exception. Thus, we need to protect the call with a catch all:

let saved_x = !x in
try
let result = x := 2; f 3 in
x := saved_x;
result
with exn -> x := saved_x; raise exn;;

This suggests a with construct to abbreviate this scheme. Something
like:

f 3 with x := 2

This has been abandonned, since the need for dynamic evaluation is not
so important. I agree that the encoding is a bit awkward but the
feature is not worth the addition of a new construct...

Pierre Weis
----------------------------------------------------------------------------
WWW Home Page: http://pauillac.inria.fr/~weis
Projet Cristal
INRIA, BP 105, F-78153 Le Chesnay Cedex (France)
E-mail: Pierre.Weis@inria.fr
Telephone: +33 1 39 63 55 98
Fax: +33 1 39 63 53 30
----------------------------------------------------------------------------