4.3. IMPERATIVE FEATURES 43
It is a matter of opinion whether exceptions are really an imperative feature.
On one view, functions just return elements of a disjoint sum consisting of their
visible return type and the type of exceptions, and all operations implicitly pass
back exceptions. Another view is that exceptions are a highly non-local control flow
perversion, analogous to goto.
2
Whatever the semantic view one takes, exceptions
can often be quite useful.
4.3.2 References and arrays
CAML does have real assignable variables, and expressions can, as a side-effect,
modify the values of these variables. They are explicitly accessed via references
(pointers in C parlance) and the references themselves behave more like ordinary
CAML values. Actually this approach is quite common in C too. For example, if one
wants so-called ‘variable parameters’ in C, where changes to the formal parameters
of a function propagate outside, the only way to do it is to pass a pointer, so that the
function can dereference it. Similar techniques are often used where the function is
to pass back composite data.
In CAML, one sets up a new assignable memory cell with the initial contents x
by writing ref x. (Initialization is compulsory.) This expression yields a reference
(pointer) to the cell. Subsequent access to the contents of the cell requires an explicit
dereference using the ! operator, similar to unary * in C. The cell is assigned to
using a conventional-looking assignment statement. For example:
#let x = ref 1;;
x : int ref = ref 1
#!x;;
it : int = 1
#x := 2;;
it : unit = ()
#!x;;
it : int = 2
#x := !x + !x;;
it : unit = ()
#x;;
it : int ref = ref 4
#!x;;
it : int = 4
Note that in most respects ref behaves like a type constructor, so one can
pattern-match against it. Thus one could actually define an indirection operator
like !:
#let contents_of (ref x) = x;;
contents_of : ’a ref -> ’a = <fun>
#contents_of x;;
it : int = 4
As well as being mutable, references are sometimes useful for creating explicitly
shared data structures. One can easily create graph structures where numerous
nodes contain a pointer to some single subgraph.
Apart from single cells, one can also use arrays in CAML. In CAML these are
called vectors. An array of elements of type α has type α vect. A fresh vector of size
n, with each element initialized to x — once again the initialization is compulsory
— is created using the following call:
2
Perhaps more precisely, to C’s setjmp and longjmp.