Version française
Home     About     Download     Resources     Contact us    

An Overview of the Caml Language and Tools

Safety

Caml is a safe language. Programs are verified by the compiler before they can be executed. This rules out many programming errors, such as, for instance, confusing an integer and a pointer, or accessing a nonexistent field in a record. More precisely, this protects the integrity of the data manipulated by a Caml program.

Although Caml is statically type-checked, it does not require that the types of function parameters, local variables, etc. be explicitly declared, contrary to, say, C or Java. Much of the necessary type information is automatically inferred by the compiler.

Functions

Caml is a functional programming language: there is no restriction on the definition and use of functions. In other words, functions are ordinary values: a function can be passed as an argument to a function or returned by a function.

Imperative features

Caml offers a full array of imperative features. In particular, variables, arrays, and record components can be declared as modifiable. Several varieties of loops are available.

Error recovery

Caml features a general exception mechanism to signal and handle errors and exceptional situations.

Data Types

Caml offers numerous built-in data types, including:

Beyond these powerful built-in types, Caml offers powerful means of defining new data types: records, enumerations, and sum types. Sum types are a simple and powerful generalization of enumerations. They allow bringing heterogeneous values together into a common type, thanks to the use of tags known as data constructors.

The types defined within a module can be made visible to the module's clients either concretely or abstractly, as the programmer desires. When a type is exported in a concrete manner, its full definition remains known: so, clients of the modules can build or examine values of this type. On the other hand, when a type is exported in an abstract manner, only its name is known outside the module. It then becomes impossible, from the outside, to create or inspect values of this type.

This mechanism provides fine-grained control over data encapsulation, which is mandatory for programming in the large.

Aptness to symbolic computation

Caml features pattern matching, a generalization of the traditional case analysis construct. Pattern matching offers a clean and elegant way of simultaneously examining and naming data. The Caml compiler takes advantage of this feature to perform several checks: superfluous as well as missing branches are detected and reported, which often allows pinpointing subtle errors. When no error is signaled, one can trust that no case has been overlooked.

Pattern matching brings unrivaled comfort and safety to programs that manipulate symbolic data.

Polymorphism

Caml features a polymorphic type system: some undetermined types can be represented by variables, which may later be instantiated at will. Thus, for instance, a single sorting function can be applied to lists of integers, lists of integer pairs, or lists of records, without requiring any code duplication.

Programming in the large

A Caml program is made of compilation units that are dealt with separately by the compiler. This scheme is fully compatible with the use of traditional project management tools, such as the “make” utility. The module system is powerful and safe: every interaction between modules is statically typechecked. In OCaml, a module may contain submodules, which allows organizing modules hierarchically, and it is possible to parameterize a module over a number of other modules, or, in other words, to define functions from modules to modules.

Object-oriented programming

OCaml allows writing programs in an object-oriented style. In keeping with the language's philosophy, the object-oriented layer obeys the “strong typing” paradigm: thus, it is impossible to send a message to some object that cannot answer it. Such safety does not come at a cost in expressiveness: thanks to features such as multiple inheritance and parametric classes, the most complex design patterns can be expressed in a natural manner.

Automatic memory management and incremental garbage collection

Caml features automatic memory management: allocation and deallocation of data structures is implicit, and dealt with by the compiler: there is no “new”, “malloc”, “delete”, or “free” operator. This makes programs much safer: memory corruption cannot occur.

Moreover, the memory manager is incremental: its execution is interleaved with that of the application, so that garbage collection does not cause noticeable delays.

Evaluation regime

Caml's evaluation strategy is strict. A lazy evaluation regime may be simulated, when required, via explicit suspensions. Thus, it is possible, for instance, to manipulate potentially infinite data streams.

Efficient compiler, efficient compiled code

OCaml offers two batch compilers: a bytecode compiler and a native code compiler. Both support separate compilation. Caml Light only offers a bytecode compiler.

The bytecode compilers generate small, portable executables. Furthermore, these compilers are extremely fast.

The native code compiler produces more efficient machine code, whose performance meets the highest standards of modern compilers.

Interactivity

Caml provides an interactive “read-eval-print” loop, which is convenient both for learning and for rapid testing and debugging of programs. Indeed, there is no need to create a file, or to insert display instructions into programs, since results are automatically printed by the interactive system.

Debugging facilities

Several different methods are available to debug Caml programs:

Parsing

Caml offers parser generation tools analogous to “lex” and “yacc” . Furthermore, it offers a built-in type of data streams which eases the definition of LL(1) recursive descent parsers.