Vous êtes sur la page 1sur 112

Developing Applications With

Objective Caml
Emmanuel Chailloux Pascal Manoury Bruno Pagano

Developing Applications With


Objective Caml

Translated by

Francisco Albacete • Mark Andrew • Martin Anlauf •


Christopher Browne • David Casperson • Gang Chen •
Harry Chomsky • Ruchira Datta • Seth Delackner •
Patrick Doane • Andreas Eder • Manuel Fahndrich •
Joshua Guttman • Theo Honohan • Xavier Leroy •
Markus Mottl • Alan Schmitt • Paul Steckler •
Perdita Stevens • François Thomasset

Éditions O’REILLY
18 rue Séguier
75006 Paris
FRANCE
france@oreilly.com
<url:http://www.editions-oreilly.fr/>

Cambridge • Cologne • Farnham • Paris • Pékin • Sebastopol • Taipei • Tokyo


The original edition of this book (ISBN 2-84177-121-0) was published in France by
O’REILLY & Associates under the title Dveloppement d’applications avec Objective
Caml.
Historique :
• Version 19990324???????????

c O’REILLY & Associates, 2000


°

Cover concept by Ellie Volckhausen.

Édition : Xavier Cazin.

Les programmes figurant dans ce livre ont pour but d’illustrer les sujets traités. Il n’est
donné aucune garantie quant à leur fonctionnement une fois compilés, assemblés ou
interprétés dans le cadre d’une utilisation professionnelle ou commerciale.

°c Éditions O’Reilly, Paris, 2000


ISBN

Toute représentation ou reproduction, intégrale ou partielle, faite sans le consentement de


l’auteur, de ses ayants droit, ou ayants cause, est illicite (loi du 11 mars 1957, alinéa 1er
de l’article 40). Cette représentation ou reproduction, par quelque procédé que ce soit, con-
stituerait une contrefaçon sanctionnée par les articles 425 et suivants du Code pénal. La loi
du 11 mars 1957 autorise uniquement, aux termes des alinéas 2 et 3 de l’article 41, les copies
ou reproductions strictement réservées à l’usage privé du copiste et non destinées à une utili-
sation collective d’une part et, d’autre part, les analyses et les courtes citations dans un but
d’exemple et d’illustration.
Preface
The desire to write a book on Objective Caml sprang from the authors’ pedagogical
experience in teaching programming concepts through the Objective Caml language.
The students in various majors and the engineers in continuing education at Pierre
and Marie Curie University have, through their dynamism and their critiques, caused
our presentation of the Objective Caml language to evolve greatly. Several examples
in this book are directly inspired by their projects.
The implementation of the Caml language has been ongoing for fifteen years. Its devel-
opment comes from the Formel and then Cristal projects at INRIA, in collaboration
with Denis Diderot University and the École Normale Supérieure. The continuous
efforts of the researchers on these teams, as much to develop the theoretical underpin-
nings as the implementation itself, have produced over the span of years a language
of very high quality. They have been able to keep pace with the constant evolution of
the field while integrating new programming paradigms into a formal framework. We
hope through this exposition to contribute to the widespread diffusion which this work
deserves.
The form and the foundation of this book wouldn’t be what they are without the help
of numerous colleagues. They were not put off by rereading our first manuscripts. Their
remarks and their comments have allowed this exposition to improve throughout the
course of its development. We wish particularly to thank Marı́a-Virginia Aponte, Syl-
vain Baro, Christian Codognet, Hélène Cottier, Guy Cousineau, Pierre Crégut, Titou
Durand, Christophe Gonzales, Michelle Morcrette, Christian Queinnec, Attila Raksany
and Didier Rémy.
The HTML version of this book would not have seen the light of day without the
tools hevea and VideoC. A big thank you to their respective authors, Luc Maranget
and Christian Queinnec, who have always responded in the briefest intervals to our
questions and our demands for changes.
vi Preface
Contents

Preface v

Table of contents vii

Introduction xxi

1: How to obtain Objective Caml 1


Description of the CD-ROM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Downloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Installation under Windows . . . . . . . . . . . . . . . . . . . . . . . . . 2
Installation under Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Installation under MacOS . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Installation from source under Unix . . . . . . . . . . . . . . . . . . . . . 5
Installation of the HTML documentation . . . . . . . . . . . . . . . . . . 5
Testing the installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

I Language Core 7

2: Functional programming 11
Functional core of Objective Caml . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Primitive values, functions, and types . . . . . . . . . . . . . . . . . . . . 12
Conditional control structure . . . . . . . . . . . . . . . . . . . . . . . . . 18
viii Table of Contents

Value declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Function expressions, functions . . . . . . . . . . . . . . . . . . . . . . . . 21
Polymorphism and type constraints . . . . . . . . . . . . . . . . . . . . . 28
Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Type declarations and pattern matching . . . . . . . . . . . . . . . . . . . . . . . 34
Pattern matching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Type declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Sum types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Recursive types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Parametrized types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Scope of declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Function types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Example: representing trees . . . . . . . . . . . . . . . . . . . . . . . . . 50
Recursive values which are not functions . . . . . . . . . . . . . . . . . . 52
Typing, domain of definition, and exceptions . . . . . . . . . . . . . . . . . . . . 54
Partial functions and exceptions . . . . . . . . . . . . . . . . . . . . . . . 54
Definition of an exception . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Raising an exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Exception handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Polymorphism and return values of functions . . . . . . . . . . . . . . . . . . . . 58
Desktop Calculator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
Merging two lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
Lexical trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Graph traversal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
To learn more . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

3: Imperative Programming 67
Modifiable Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Character Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
Mutable Fields of Records . . . . . . . . . . . . . . . . . . . . . . . . . . 73
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Polymorphism and Modifiable Values . . . . . . . . . . . . . . . . . . . . 74
Input-Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Channels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Reading and Writing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Example: Higher/Lower . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Control Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Example: Implementing a Stack . . . . . . . . . . . . . . . . . . . . . . . 82
Example: Calculations on Matrices . . . . . . . . . . . . . . . . . . . . . 84
Order of Evaluation of Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Table of Contents ix

Calculator With Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86


Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Doubly Linked Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Solving linear systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

4: Functional and Imperative Styles 91


Comparison between Functional and Imperative . . . . . . . . . . . . . . . . . . 92
The Functional Side . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
The Imperative Side . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Recursive or Iterative . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Which Style to Choose? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
Sequence or Composition of Functions . . . . . . . . . . . . . . . . . . . . 97
Shared or Copy Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
How to Choose your Style . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Mixing Styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Closures and Side Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Physical Modifications and Exceptions . . . . . . . . . . . . . . . . . . . 105
Modifiable Functional Data Structures . . . . . . . . . . . . . . . . . . . 105
Lazy Modifiable Data Structures . . . . . . . . . . . . . . . . . . . . . . . 107
Streams of Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
Construction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
Destruction and Matching of Streams . . . . . . . . . . . . . . . . . . . . 111
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
Binary Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
Spelling Corrector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Set of Prime Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

5: The Graphics Interface 117


Using the Graphics Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Basic notions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Graphical display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
Reference point and graphical context . . . . . . . . . . . . . . . . . . . . 119
Colors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Drawing and filling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
Bitmaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
Example: drawing of boxes with relief patterns . . . . . . . . . . . . . . . 126
Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
Types and functions for events . . . . . . . . . . . . . . . . . . . . . . . . 132
Program skeleton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
x Table of Contents

Example: telecran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134


A Graphical Calculator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Polar coordinates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Bitmap editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
Earth worm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
To learn more . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

6: Applications 147
Database queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Data format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Reading a database from a file . . . . . . . . . . . . . . . . . . . . . . . . 150
General principles for database processing . . . . . . . . . . . . . . . . . 151
Selection criteria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
Processing and computation . . . . . . . . . . . . . . . . . . . . . . . . . 156
An example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Further work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
BASIC interpreter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Abstract syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
Program pretty printing . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
Lexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
Parsing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Finishing touches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
Further work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Minesweeper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
The abstract mine field . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
Displaying the Minesweeper game . . . . . . . . . . . . . . . . . . . . . . 182
Interaction with the player . . . . . . . . . . . . . . . . . . . . . . . . . . 188
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

II Development Tools 193

7: Compilation and Portability 197


Steps of Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
The Objective Caml Compilers . . . . . . . . . . . . . . . . . . . . . . . . 198
Description of the Bytecode Compiler . . . . . . . . . . . . . . . . . . . . 199
Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Command Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Compilation Unit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Naming Rules for File Extensions . . . . . . . . . . . . . . . . . . . . . . 202
The Bytecode Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
Native Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
Table of Contents xi

Toplevel Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205


Construction of a New Interactive System . . . . . . . . . . . . . . . . . 206
Standalone Executables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
Portability and Efficiency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
Standalone Files and Portability . . . . . . . . . . . . . . . . . . . . . . . 208
Efficiency of Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
Creation of a Toplevel and Standalone Executable . . . . . . . . . . . . . 209
Comparison of Performance . . . . . . . . . . . . . . . . . . . . . . . . . 209
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210

8: Libraries 213
Categorization and Use of the Libraries . . . . . . . . . . . . . . . . . . . . . . . 214
Preloaded Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Standard Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
Linear Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
Input-output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
Persistence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
Interface with the System . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
Other Libraries in the Distribution . . . . . . . . . . . . . . . . . . . . . . . . . . 239
Exact Math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
Dynamic Loading of Code . . . . . . . . . . . . . . . . . . . . . . . . . . 241
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
Resolution of Linear Systems . . . . . . . . . . . . . . . . . . . . . . . . . 244
Search for Prime Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . 244
Displaying Bitmaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246

9: Garbage Collection 247


Program Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
Allocation and Deallocation of Memory . . . . . . . . . . . . . . . . . . . . . . . 249
Explicit Allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
Explicit Reclamation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
Implicit Reclamation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
Automatic Garbage Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
Reference Counting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
Sweep Algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
Mark&Sweep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
Stop&Copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
Other Garbage Collectors . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
Memory Management by Objective Caml . . . . . . . . . . . . . . . . . . . . . . 261
Module Gc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
xii Table of Contents

Module Weak . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265


Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
Following the evolution of the heap . . . . . . . . . . . . . . . . . . . . . 268
Memory Allocation and Programming Styles . . . . . . . . . . . . . . . . 269
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269

10 : Program Analysis Tools 271


Dependency Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
Debugging Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
Trace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
Debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
Execution Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
Profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Compilation Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Program Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
Presentation of the Results . . . . . . . . . . . . . . . . . . . . . . . . . . 283
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
Tracing Function Application . . . . . . . . . . . . . . . . . . . . . . . . . 285
Performance Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286

11 : Tools for lexical analysis and parsing 287


Lexicon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
Module Genlex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
Use of Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
Regular Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
The Str Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
The ocamllex Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
Grammar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
Production and Recognition . . . . . . . . . . . . . . . . . . . . . . . . . 296
Top-down Parsing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
Bottom-up Parsing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
The ocamlyacc Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
Contextual Grammars . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
Basic Revisited . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
File basic parser.mly . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
File basic lexer.mll . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
Compiling, Linking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
Filtering Comments Out . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
Evaluator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
Table of Contents xiii

To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313

12 : Interoperability with C 315


Communication between C and Objective Caml . . . . . . . . . . . . . . . . . . . 317
External declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
Declaration of the C functions . . . . . . . . . . . . . . . . . . . . . . . . 318
Linking with C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320
Mixing input-output in C and in Objective Caml . . . . . . . . . . . . . 323
Exploring Objective Caml values from C . . . . . . . . . . . . . . . . . . . . . . . 323
Classification of Objective Caml representations . . . . . . . . . . . . . . 324
Accessing immediate values . . . . . . . . . . . . . . . . . . . . . . . . . . 325
Representation of structured values . . . . . . . . . . . . . . . . . . . . . 326
Creating and modifying Objective Caml values from C . . . . . . . . . . . . . . . 335
Modifying Objective Caml values . . . . . . . . . . . . . . . . . . . . . . 336
Allocating new blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337
Storing C data in the Objective Caml heap . . . . . . . . . . . . . . . . . 338
Garbage collection and C parameters and local variables . . . . . . . . . 341
Calling an Objective Caml closure from C . . . . . . . . . . . . . . . . . 343
Exception handling in C and in Objective Caml . . . . . . . . . . . . . . . . . . 344
Raising a predefined exception . . . . . . . . . . . . . . . . . . . . . . . . 344
Raising a user-defined exception . . . . . . . . . . . . . . . . . . . . . . . 345
Catching an exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
Main program in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
Linking Objective Caml code with C . . . . . . . . . . . . . . . . . . . . 347
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
Polymorphic Printing Function . . . . . . . . . . . . . . . . . . . . . . . . 348
Matrix Product . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
Counting Words: Main Program in C . . . . . . . . . . . . . . . . . . . . 348
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349

13 : Applications 351
Constructing a Graphical Interface . . . . . . . . . . . . . . . . . . . . . . . . . . 351
Graphics Context, Events and Options . . . . . . . . . . . . . . . . . . . 352
Components and Containers . . . . . . . . . . . . . . . . . . . . . . . . . 356
Event Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
Defining Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
Enriched Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
Setting up the Awi Library . . . . . . . . . . . . . . . . . . . . . . . . . . 377
Example: A Franc-Euro Converter . . . . . . . . . . . . . . . . . . . . . . 378
Where to go from here . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380
Finding Least Cost Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381
Graph Representions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
Dijkstra’s Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
Introducing a Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
xiv Table of Contents

A Graphical Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392


Creating a Standalone Application . . . . . . . . . . . . . . . . . . . . . . 398
Final Notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400

III Application Structure 401

14 : Programming with Modules 405


Modules as Compilation Units . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406
Interface and Implementation . . . . . . . . . . . . . . . . . . . . . . . . 406
Relating Interfaces and Implementations . . . . . . . . . . . . . . . . . . 408
Separate Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
The Module Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410
Two Stack Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
Modules and Information Hiding . . . . . . . . . . . . . . . . . . . . . . . 414
Type Sharing between Modules . . . . . . . . . . . . . . . . . . . . . . . 416
Extending Simple Modules . . . . . . . . . . . . . . . . . . . . . . . . . . 418
Parameterized Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
Functors and Code Reuse . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
Local Module Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . 422
Extended Example: Managing Bank Accounts . . . . . . . . . . . . . . . . . . . . 423
Organization of the Program . . . . . . . . . . . . . . . . . . . . . . . . . 423
Signatures for the Module Parameters . . . . . . . . . . . . . . . . . . . . 424
The Parameterized Module for Managing Accounts . . . . . . . . . . . . 426
Implementing the Parameters . . . . . . . . . . . . . . . . . . . . . . . . 427
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431
Association Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431
Parameterized Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431
Lexical Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433

15 : Object-Oriented Programming 435


Classes, Objects, and Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436
Object-Oriented Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 436
Class Declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437
Instance Creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
Sending a Message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
Relations between Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441
Aggregation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441
Inheritance Relation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443
Other Object-oriented Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445
References: self and super . . . . . . . . . . . . . . . . . . . . . . . . . 445
Delayed Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
Object Representation and Message Dispatch . . . . . . . . . . . . . . . . 447
Table of Contents xv

Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448
Private Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
Types and Genericity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450
Abstract Classes and Methods . . . . . . . . . . . . . . . . . . . . . . . . 450
Classes, Types, and Objects . . . . . . . . . . . . . . . . . . . . . . . . . 452
Multiple Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
Parameterized Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460
Subtyping and Inclusion Polymorphism . . . . . . . . . . . . . . . . . . . . . . . 465
Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465
Subtyping is not Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . 466
Inclusion Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468
Equality between Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . 469
Functional Style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469
Other Aspects of the Object Extension . . . . . . . . . . . . . . . . . . . . . . . 473
Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473
Local Declarations in Classes . . . . . . . . . . . . . . . . . . . . . . . . . 474
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477
Stacks as Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477
Delayed Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477
Abstract Classes and an Expression Evaluator . . . . . . . . . . . . . . . 479
The Game of Life and Objects. . . . . . . . . . . . . . . . . . . . . . . . . 479
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480

16 : Comparison of the Models of Organisation 483


Comparison of Modules and Objects . . . . . . . . . . . . . . . . . . . . . . . . . 484
Translation of Modules into Classes . . . . . . . . . . . . . . . . . . . . . 487
Simulation of Inheritance with Modules . . . . . . . . . . . . . . . . . . . 489
Limitations of each Model . . . . . . . . . . . . . . . . . . . . . . . . . . 490
Extending Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 492
In the Functional Model . . . . . . . . . . . . . . . . . . . . . . . . . . . 493
In the Object Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493
Extension of Data and Methods . . . . . . . . . . . . . . . . . . . . . . . 495
Mixed Organisations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
Classes and Modules for Data Structures . . . . . . . . . . . . . . . . . . 498
Abstract Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 499
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 499
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 499

17 : Applications 501
Two Player Games . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501
The Problem of Two Player Games . . . . . . . . . . . . . . . . . . . . . 502
Minimax αβ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503
Organization of a Game Program . . . . . . . . . . . . . . . . . . . . . . 510
xvi Table of Contents

Connect Four . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515


Stonehenge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549
Fancy Robots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
“Abstract” Robots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551
Pure World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 553
Textual Robots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554
Textual World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 556
Graphical Robots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 559
Graphical World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 562
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563

IV Concurrency and distribution 565

18 : Communication and Processes 571


The Unix Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 572
Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573
Portability of System Calls . . . . . . . . . . . . . . . . . . . . . . . . . . 573
File Descriptors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573
File Manipulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575
Input / Output on Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579
Executing a Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579
Process Creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581
Creation of Processes by Duplication . . . . . . . . . . . . . . . . . . . . 582
Order and Moment of Execution . . . . . . . . . . . . . . . . . . . . . . . 584
Descendence, Death and Funerals of Processes . . . . . . . . . . . . . . . 586
Communication Between Processes . . . . . . . . . . . . . . . . . . . . . . . . . . 587
Communication Pipes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 587
Communication Channels . . . . . . . . . . . . . . . . . . . . . . . . . . . 589
Signals under Unix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 590
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 595
Counting Words: the wc Command . . . . . . . . . . . . . . . . . . . . . 595
Pipes for Spell Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . 595
Interactive Trace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596

19 : Concurrent Programming 599


Concurrent Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600
Compilation with Threads . . . . . . . . . . . . . . . . . . . . . . . . . . 601
Module Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 602
Synchronization of Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604
Critical Section and Mutual Exclusion . . . . . . . . . . . . . . . . . . . . 604
Table of Contents xvii

Mutex Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604


Waiting and Synchronization . . . . . . . . . . . . . . . . . . . . . . . . . 608
Condition Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609
Synchronous Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 612
Synchronization using Communication Events . . . . . . . . . . . . . . . 612
Transmitted Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 612
Module Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 613
Example: Post Office . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614
The Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 615
Clients and Clerks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 617
The System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 618
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 619
The Philosophers Disentangled . . . . . . . . . . . . . . . . . . . . . . . . 619
More of the Post Office . . . . . . . . . . . . . . . . . . . . . . . . . . . . 619
Object Producers and Consumers . . . . . . . . . . . . . . . . . . . . . . 619
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 620
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 621

20 : Distributed Programming 623


The Internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 624
The Unix Module and IP Addressing . . . . . . . . . . . . . . . . . . . . 625
Sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627
Description and Creation . . . . . . . . . . . . . . . . . . . . . . . . . . . 627
Addresses and Connections . . . . . . . . . . . . . . . . . . . . . . . . . . 629
Client-server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 630
Client-server Action Model . . . . . . . . . . . . . . . . . . . . . . . . . . 630
Client-server Programming . . . . . . . . . . . . . . . . . . . . . . . . . . 631
Code for the Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 632
Testing with telnet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 634
The Client Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635
Client-server Programming with Lightweight Processes . . . . . . . . . . 639
Multi-tier Client-server Programming . . . . . . . . . . . . . . . . . . . . 642
Some Remarks on the Client-server Programs . . . . . . . . . . . . . . . 642
Communication Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 643
Text Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 644
Protocols with Acknowledgement and Time Limits . . . . . . . . . . . . 646
Transmitting Values in their Internal Representation . . . . . . . . . . . 646
Interoperating with Different Languages . . . . . . . . . . . . . . . . . . 647
Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 647
Service: Clock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 648
A Network Coffee Machine . . . . . . . . . . . . . . . . . . . . . . . . . . 648
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649

21 : Applications 651
xviii Table of Contents

Client-server Toolbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651


Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 652
Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 652
Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 653
Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 656
The Robots of Dawn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 656
World-Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 657
Observer-client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661
Robot-Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 663
To Learn More . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 665
HTTP Servlets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 665
HTTP and CGI Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . 666
HTML Servlet Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . 671
Dynamic Pages for Managing the Association Database . . . . . . . . . . 674
Analysis of Requests and Response . . . . . . . . . . . . . . . . . . . . . 676
Main Entry Point and Application . . . . . . . . . . . . . . . . . . . . . . 676

22 : Developing applications with Objective Caml 679


Elements of the evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 680
Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 680
Libraries and tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 681
Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 682
Other development tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 682
Editing tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 683
Syntax extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 683
Interoperability with other languages . . . . . . . . . . . . . . . . . . . . 683
Graphical interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 683
Parallel programming and distribution . . . . . . . . . . . . . . . . . . . 684
Applications developed in Objective Caml . . . . . . . . . . . . . . . . . . . . . . 685
Similar functional languages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 686
ML family . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 686
Scheme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 687
Languages with delayed evaluation . . . . . . . . . . . . . . . . . . . . . . 688
Communication languages . . . . . . . . . . . . . . . . . . . . . . . . . . 690
Object-oriented languages: comparison with Java . . . . . . . . . . . . . . . . . . 691
Main characteristics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 691
Differences with Objective Caml . . . . . . . . . . . . . . . . . . . . . . . 691
Future of Objective Caml development . . . . . . . . . . . . . . . . . . . . . . . . 693

Conclusion 695
Table of Contents xix

V Appendices 697

A: Cyclic Types 699


Cyclic types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 699
Option -rectypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 701

B: Objective Caml 3.04 703


Language Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 703
Labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 704
Optional arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706
Labels and objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 708
Polymorphic variants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 709
LablTk Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712
OCamlBrowser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712

Bibliography 715

Index of concepts 719

Index of language elements 725


Introduction
Objective Caml is a programming language. One might ask why yet another lan-
guage is needed. Indeed there are already numerous existing languages with new ones
constantly appearing. Beyond their differences, the conception and genesis of each one
of them proceeds from a shared motivation: the desire to abstract.

To abstract from the machine In the first place, a programming language permits
one to neglect the “mechanical” aspect of the computer; it even lets one forget
the microprocessor model or the operating system on which the program will be
executed.
To abstract from the operational model The notion of function which most lan-
guages possess in one form or another is borrowed from mathematics and not
from electronics. In a general way, languages substitute formal models for purely
computational viewpoints. Thus they gain expressivity.
To abstract errors This has to do with the attempt to guarantee execution safety; a
program shouldn’t terminate abruptly or become inconsistent in case of an error.
One of the means of attaining this is strong static typing of programs and having
an exception mechanism in place.
To abstract components (i) Programming languages make it possible to subdivide
an application into different software components which are more or less indepen-
dent and autonomous. Modularity permits higher-level structuring of the whole
of a complex application.
To abstract components (ii) The existence of programming units has opened up
the possibility of their reuse in contexts other than the ones for which they were
developed. Object-oriented languages constitute another approach to reusability
permitting rapid prototyping.

Objective Caml is a recent language which takes its place in the history of program-
ming languages as a distant descendant of Lisp, having been able to draw on the lessons
xxii Introduction

of its cousins while incorporating the principal characteristics of other languages. It is


developed at INRIA1 and is supported by long experience with the conception of the
languages in the ML family. Objective Caml is a general-purpose language for the
expression of symbolic and numeric algorithms. It is object-oriented and has a param-
eterized module system. It supports the development of concurrent and distributed
applications. It has excellent execution safety thanks to its static typing, its exception
mechanism and its garbage collector. It is high-performance while still being portable.
Finally, a rich development environment is available.
Objective Caml has never been the subject of a presentation to the “general public”.
This is the task to which the authors have set themselves, giving this exposition three
objectives:
1. To describe in depth the Objective Caml language, its libraries and its develop-
ment environment.
2. To show and explain what are the concepts hidden behind the programming
styles which can be used with Objective Caml.
3. To illustrate through numerous examples how Objective Caml can serve as the
development language for various classes of applications.

The authors’ goal is to provide insight into how to choose a programming style and
structure a program, consistent with a given problem, so that it is maintainable and
its components are reusable.

Description of the language


Objective Caml is a functional language: it manipulates functions as values in
the language. These can in turn be passed as arguments to other functions or returned
as the result of a function call.

Objective Caml is statically typed: verification of compatibility between the


types of formal and actual parameters is carried out at program compilation time.
From then on it is not necessary to perform such verification during the execution of
the program, which increases its efficiency. Moreover, verification of typing permits the
elimination of most errors introduced by typos or thoughtlessness and contributes to
execution safety.

Objective Caml has parametric polymorphism: a function which does not tra-
verse the totality of the structure of one of its arguments accepts that the type of this
argument is not fully determined. In this case this parameter is said to be polymorphic.
This feature permits development of generic code usable for different data structures,

1. Institut National de Recherche en Informatique et Automatique (National Institute for Research


in Automation and Information Technology).
Introduction xxiii

such that the exact representation of this structure need not be known by the code in
question. The typing algorithm is in a position to make this distinction.

Objective Caml has type inference: the programmer need not give any type
information within the program. The language alone is in charge of deducing from the
code the most general type of the expressions and declarations therein. This inference
is carried out jointly with verification, during program compilation.

Objective Caml is equipped with an exception mechanism: it is possible to


interrupt the normal execution of a program in one place and resume at another place
thanks to this facility. This mechanism allows control of exceptional situations, but it
can also be adopted as a programming style.

Objective Caml has imperative features: I/O, physical modification of values


and iterative control structures are possible without having recourse to functional pro-
gramming features. Mixture of the two styles is acceptable, and offers great develop-
ment flexibility as well as the possibility of defining new data structures.

Objective Caml executes (threads): the principal tools for creation, synchroniza-
tion, management of shared memory, and interthread communication are predefined.

Objective Caml communicates on the Internet: the support functions needed


to open communication channels between different machines are predefined and permit
the development of client-server applications.

Numerous libraries are available for Objective Caml: classic data structures,
I/O, interfacing with system resources, lexical and syntactic analysis, computation with
large numbers, persistent values, etc.

A programming environment is available for Objective Caml: including in-


teractive toplevel, execution trace, dependency calculation and profiling.

Objective Caml interfaces with the C language: by calling C functions from


an Objective Caml program and vice versa, thus permitting access to numerous C
libraries.

Three execution modes are available for Objective Caml: interactive by


means of an interactive toplevel, compilation to bytecodes interpreted by a virtual ma-
chine, compilation to native machine code. The programmer can thus choose between
xxiv Introduction

flexibility of development, portability of object code between different architectures, or


performance on a given architecture.

Structure of a program
Development of important applications requires the programmer or the development
team to consider questions of organization and structure. In Objective Caml, two mod-
els are available with distinct advantages and features.

The parameterized module model: data and procedures are gathered within a
single entity with two facets: the code proper, and its interface. Communication be-
tween modules takes place via their interface. The description of a type may be hidden,
not appearing in the module interface. These abstract data types facilitate modifica-
tions of the internal implementation of a module without affecting other modules which
use it. Moreover, modules can be parameterized by other modules, thus increasing their
reusability.

The object model: descriptions of procedures and data are gathered into enti-
ties called classes; an object is an instance (value) of a class. Interobject communica-
tion is implemented through “message passing”, the receiving object determines upon
execution (late binding) the procedure corresponding to the message. In this way,
object-oriented programming is “data-driven”. The program structure comes from the
relationships between classes; in particular inheritance lets one class be defined by
extending another. This model allows concrete, abstract and parameterized classes.
Furthermore, it introduces polymorphism of inclusion by defining the subtyping rela-
tionship between classes.

The choice between these two models allows great flexibility in the logical organization
of an application and facilitates its maintenance and evolution. There is a duality
between these two models. One cannot add data fields to a module type (no extensibility
of data), but one can add new procedures (extensibility of procedures) acting on data.
In the object model, one can add subclasses of a class (extensibility of data) for dealing
with new cases, but one cannot add new procedures visible from the ancestor class
(no extensibility of procedures). Nevertheless the combination of the two offers new
possibilities for extending data and procedures.

Safety and efficiency of execution


Objective Caml bestows excellent execution safety on its programs without sacrificing
their efficiency. Fundamentally, static typing is a guarantee of the absence of run-
time type errors and makes useful static information available to the compiler without
burdening performance with dynamic type tests. These benefits also extend to the
object-oriented language features. Moreover, the built-in garbage collector adds to the
safety of the language system. Objective Caml’s is particularly efficient. The exception
Introduction xxv

mechanism guarantees that the program will not find itself in an inconsistent state
after a division by zero or an access outside the bounds of an array.

Outline of the book


The present work consists of four main parts, bracketed by two chapters and enhanced
by two appendices, a bibliography, an index of language elements and an index of
programming concepts.

Chapter 1 : This chapter describes how to install version 2.04 of the Objective Caml
language on the most current systems (Windows, Unix and MacOS).
Part I: Core of the language The first part is a complete presentation of the basic
elements of the Objective Caml language. Chapter 2 is a dive into the func-
tional core of the language. Chapter 3 is a continuation of the previous one and
describes the imperative part of the language. Chapter 4 compares the “pure”
functional and imperative styles, then presents their joint use. Chapter 5 presents
the graphics library. Chapter 6 exhibits three applications: management of a
simple database, a mini-Basic interpreter and a well-known single-player game,
minesweeper.
Part II: Development tools The second part of the book describes the various tools
for application development. Chapter 7 compares the various compilation modes,
which are the interactive toplevel and command-line bytecode and native code
compilers. Chapter 8 presents the principal libraries provided with the language
distribution. Chapter 9 explains garbage collection mechanisms and details the
one used by Objective Caml. Chapter 10 explains the use of tools for debug-
ging and profiling programs. Chapter 11 addresses lexical and syntactic tools.
Chapter 12 shows how to interface Objective Caml programs with C. Chapter
13 constructs a library and an application. This library offers tools for the con-
struction of GUIs. The application is a search for least-cost paths within a graph,
whose GUI uses the preceding library.
Part III: Organization of applications The third part describes the two ways of
organizing a program: with modules, and with objects. Chapter 14 is a presenta-
tion of simple and parameterized language modules. Chapter 15 introduces Ob-
jective Caml object-oriented extension. Chapter 16 compares these two types of
organization and indicates the usefulness of mixing them to increase the extensi-
bility of programs. Chapter 17 describes two substantial applications: two-player
games which put to work several parameterized modules used for two different
games, and a simulation of a robot world demonstrating interobject communica-
tion.
Part IV: Concurrence and distribution The fourth part introduces concurrent
and distributed programs while detailing communication between processes, lightweight
or not, and on the Internet. Chapter 18 demonstrates the direct link between
the language and the system libraries, in particular the notions of process and
xxvi Introduction

communication. Chapter 19 leads to the lack of determinism of concurrent pro-


gramming while presenting Objective Caml’s threads. Chapter 20 discusses in-
terprocess communication via sockets in the distributed memory model. Chapter
21 presents first of all a toolbox for client-server applications. It is subsequently
used to extend the robots of the previous part to the client-server model. Finally,
we adapt some of the programs already encountered in the form of an HTTP
server.
Chapter 22 This last chapter takes stock of application development in Objective
Caml and presents the best-known applications of the ML language family.
Appendices The first appendix explains the notion of cyclic types used in the typ-
ing of objects. The second appendix describes the language changes present in
the new version 3.00. These have been integrated in all following versions of
Objective Caml (3.xx).

Each chapter consists of a general presentation of the subject being introduced, a


chapter outline, the various sections thereof, statements of exercises to carry out, a
summary, and a final section entitled “To learn more” which indicates bibliographic
references for the subject which has been introduced.
1
How to obtain
Objective Caml

The various programs used in this work are “free” software 1 . They can be found either
on the CD-ROM accompanying this work, or by downloading them from the Internet.
This is the case for Objective Caml, developed at Inria.

Description of the CD-ROM


The CD-ROM is provided as a hierarchy of files. At the root can be found the file
index.html which presents the CD-ROM, as well as the five subdirectories below:
• book: root of the HTML version of the book along with the solutions to the
exercises;
• apps: applications described in the book;
• exercises: independent solutions to the proposed exercises;
• distrib: set of distributions provided by Inria, as described in the next section;
• tools: set of tools for development in Objective Caml;
• docs: online documentation of the distribution and the tools.

To read the CD-ROM, start by opening the file index.html in the root using your
browser of choice. To access directly the hypertext version of the book, open the file
book/index.html. This file hierarchy, updated in accordance with readers’ remarks,
can be found posted on the editor’s site:

Link: http://www.oreilly.fr

1. “Free software” is not to be confused with “freeware”. “Freeware” is software which costs nothing,
whereas “free software” is software whose source is also freely available. In the present case, all the
programs used cost nothing and their source is available.
2 Chapter 1 : How to obtain Objective Caml

Downloading
Objective Caml can be downloaded via web browser at the following address:

Link: http://caml.inria.fr/ocaml/distrib.html

There one can find binary distributions for Linux (Intel and PPC), for Windows (NT,
95, 98) and for MacOS (7, 8), as well as documentation, in English, in different formats
(PDF, PostScript and HTML). The source code for the three systems is available
for download as well. Once the desired distribution is copied to one’s machine, it’s time
to install it. This procedure varies according to the operating system used.

Installation
Installing Objective Caml requires about 10MB of free space on one’s hard disk drive.
The software can easily be uninstalled without corrupting the system.

Installation under Windows


The file containing the binary distribution is called: ocaml-2.04-win.zip, indicating
the version number (here 2.04) and the operating system.

Objective Caml only works under recent versions of


Warning Windows : Windows 95, 98 and NT. Don’t try to in-
stall it under Windows 3.x or OS2/Warp.

1. The file is in compressed (.zip) format; the first thing to do is decompress it.
Use your favorite decompression software for this. You obtain in this way a file
hierarchy whose root is named ocaml. You can place this directory at any location
on your hard disk. It is denoted by <caml-dir> in what follows.
2. This directory includes:
• two subdirectories: bin for binaries and lib for libraries;
• two “text” files: License.txt and Changes.txt containing the license to
use the software and the changes relative to previous versions;
• an application: OCamlWin corresponding to the main application;
• a configuration file: Ocamlwin.ini which will need to be modified (see the
following point);
• two files of version notes: the first, Readme.gen, for this version and the
second, Readme.win, for the version under Windows.
3. If you have chosen a directory other than c:\ocaml as the root of your file
hierarchy, then it is necessary to indicate this in the configuration file. Edit it
with Wordpad and change the line defining CmdLine which is of the form:
CmdLine=ocamlrun c:\ocaml\bin\ocaml.exe -I c:\ocaml\lib
to
Installation 3

CmdLine=ocamlrun <caml-dir>\bin\ocaml.exe -I <caml-dir>\lib


You have to replace the names of the search paths for binaries and libraries with
the name of the Objective Caml root directory. If we have chosen C:\Lang\ocaml
as the root directory (<caml-dir>), the modification becomes:
CmdLine=ocamlrun C:\Lang\ocaml\bin\ocaml.exe -I C:\Lang\ocaml\lib
4. Copy the file OCamlWin.ini to the main system directory, that is, C:\windows
or C:\win95 or C:\winnt according to the installation of your system.
Now it’s time to test the OCamlWin application by double-clicking on it. You’ll get the
window in figure 1.1.

Figure 1.1: Objective Caml window under Windows.

The configuration of command-line executables, launched from a DOS window, is done


by modifying the PATH variable and the Objective Caml library search path vari-
able (CAMLLIB), as follows:

PATH=%PATH%;<caml-dir>\bin
set CAMLLIB=<caml-dir>\lib

where <caml-dir> is replaced by the path where Objective Caml is installed.


4 Chapter 1 : How to obtain Objective Caml

These two commands can be included in the autoexec.bat file which every good DOS
has. To test the command-line executables, type the command ocaml in a DOS window.
This executes the file:

<caml-dir>/bin/ocaml.exe

corresponding to the Objective Caml. text mode toplevel. To exit from this command,
type #quit;;.
To install Objective Caml from source under Windows is not so easy, because it requires
the use of commercial software, in particular the Microsoft C compiler. Refer to the
file Readme.win of the binary distribution to get the details.

Installation under Linux


The Linux installation also has an easy-to-install binary distribution in the form of an
rpm. package. Installation from source is described in section 1. The file to download
is: ocaml-2.04-2.i386.rpm which will be used as follows with root privileges:

rpm -i ocaml-2.04-2.i386.rpm

which installs the executables in the /usr/bin directory and the libraries in the
/usr/lib/ocaml directory.

To test the installation, type: ocamlc -v which prints the version of Objective Caml
installed on the machine.

ocamlc -v
The Objective Caml compiler, version 2.04
Standard library directory: /usr/lib/ocaml

You can also execute the command ocaml which prints the header of the interactive
toplevel.

Objective Caml version 2.04

The # character is the prompt in the interactive toplevel. This interactive toplevel can
be exited by the #quit;; directive, or by typing CTRL-D. The two semi-colons indicate
the end of an Objective Caml phrase.

Installation under MacOS


The MacOS distribution is also in the form of a self-extracting binary. The file to
download is: ocaml-2.04-mac.sea.bin which is compressed. Use your favorite software
Testing the installation 5

to decompress it. Then all you have to do to install it is launch the self-extracting
archive and follow the instructions printed in the dialog box to choose the location
of the distribution. For the MacOS X server distribution, follow the installation from
source under Unix.

Installation from source under Unix


Objective Caml can be installed on systems in the Unix family from the source dis-
tribution. Indeed it will be necessary to compile the Objective Caml system. To do
this, one must either have a C compiler on one’s Unix, machine, which is generally
the case, or download one such as gcc which works on most Unix. systems. The Ob-
jective Caml distribution file containing the source is: ocaml-2.04.tar.gz. The file
INSTALL describes, in a very clear way, the various stages of configuring, making, and
then installing the binaries.

Installation of the HTML documentation


Objective Caml’s English documentation is present also in the form of a hierarchy of
HTML files which can be found in the docs directory of the CD-ROM.
This documentation is a reference manual. It is not easy reading for the beginner.
Nevertheless it is quite useful as a description of the language, its tools, and its libraries.
It will soon become indispensable for anyone who hopes to write a program of more
than ten lines.

Testing the installation


Once installation of the Objective Caml development environment is done, it is nec-
essary to test it, mainly to verify the search paths for executables and libraries. The
simplest way is to launch the interactive toplevel of the system and write the first little
program that follows:

String.concat "/" ["a"; "path"; "here"] ;;

This expression concatenates several character strings, inserting the “/” character be-
tween each word. The notation String.concat indicates use of the function concat
from the String. If the library search path is not correct, the system will print an error.
It will be noted that the system indicates that the computation returns a character
string and prints the result.
The documentation of this function String.concat can be found in the online reference
manual by following the links “The standard library” then “Module String: string
operations”.
To exit the interactive toplevel, the user must type the directive “#quit ;;”.
6 Chapter 1 : How to obtain Objective Caml
Part I

Language Core

7
9

The first part of this book is a complete introduction to the core of the Objective
Caml language, in particular the expression evaluation mechanism, static typing and
the data memory model.
An expression is the description of a computation. Evaluation of an expression returns
a value at the end of the computation. The execution of an Objective Caml program
corresponds to the computation of an expression. Functions, program execution control
structures, even conditions or loops, are themselves also expressions.
Static typing guarantees that the computation of an expression cannot cause a run-time
type error. In fact, application of a function to some arguments (or actual parameters)
isn’t accepted unless they all have types compatible with the formal parameters indi-
cated in the definition of the function. Furthermore, the Objective Caml language has
type infererence: the compiler automatically determines the most general type of an
expression.
Finally a minimal knowledge of the representation of data is indispensable to the
programmer in order to master the effects of physical modifications to the data.

Outline
Chapter 2 contains a complete presentation of the purely functional part of the lan-
guage and the constraints due to static typing. The notion of expression evaluation is
illustrated there at length. The following control structures are detailed: conditional,
function application and pattern matching. The differences between the type and the
domain of a function are discussed in order to introduce the exception mechanism. This
feature of the language goes beyond the functional context and allows management of
computational breakdowns.
Chapter 3 exhibits the imperative style. The constructions there are closer to classic
languages. Associative control structures such as sequence and iteration are presented
there, as well as mutable data structures. The interaction between physical modifica-
tions and sharing of data is then detailed. Type inference is described there in the
context of these new constructions.
Chapter 4 compares the two preceding styles and especially presents different mixed
styles. This mixture supports in particular the construction of lazy data structures,
including mutable ones.

Chapter 5 demonstrates the use of the Graphics library included in the language
distribution. The basic notions of graphics programming are exhibited there and im-
mediately put into practice. There’s even something about GUI construction thanks
to the minimal event control provided by this library.
These first four chapters are illustrated by a complete example, the implementation
of a calculator, which evolves from chapter to chapter.
Chapter 6 presents three complete applications: a little database, a mini-BASIC inter-
preter and the game Minesweeper. The first two examples are constructed mainly in a
functional style, while the third is done in an imperative style.
10

The rudiments of syntax


Before beginning we indicate the first elements of the syntax of the language. A program
is a sequence of phrases in the language. A phrase is a complete, directly executable
syntactic element (an expression, a declaration). A phrase is terminated with a double
semi-colon (; ;). There are three different types of declarations which are each marked
with a different keyword:

value declaration : let


exception declaration : exception
type declaration : type

All the examples given in this part are to be input into the interactive toplevel of the
language.
Here’s a first (little) Objective Caml program, to be entered into the toplevel, whose
prompt is the pound character (#), in which a function fact computing the factorial
of a natural number, and its application to a natural number 8, are defined.
# let rec fact n = if n < 2 then 1 else n * fact(n-1) ; ;
val fact : int -> int = <fun>
# fact 8 ; ;
- : int = 40320
This program consists of two phrases. The first is the declaration of a function value
and the second is an expression. One sees that the toplevel prints out three pieces
of information which are: the name being declared, or a dash (-) in the case of an
expression; the inferred type; and the return value. In the case of a function value, the
system prints <fun>.
The following example demonstrates the manipulation of functions as values in the
language. There we first of all define the function succ which calculates the successor
of an integer, then the function compose which composes two functions. The latter will
be applied to fact and succ.

# let succ x = x+1 ; ;


val succ : int -> int = <fun>
# let compose f g x = f(g x) ; ;
val compose : (’a -> ’b) -> (’c -> ’a) -> ’c -> ’b = <fun>
# compose fact succ 8 ; ;
- : int = 362880
This last call carries out the computation fact(succ 8) and returns the expected
result. Let us note that the functions fact and succ are passed as parameters to
compose in the same way as the natural number 8.
2
Functional
programming

The first functional language, Lisp, appeared at the end of the 1950’s. That is, at
the same time as Fortran, the first representative of the imperative languages. These
two languages still exist, although both have evolved greatly. They are used widely for
numerical programming (in the case of Fortran) and symbolic applications in the case of
Lisp. Interest in functional programming arises from the great ease of writing programs
and specifying the values which they manipulate. A program is a function applied to its
arguments. It computes a result which is returned (when the computation terminates)
as the output of the program. In this way it becomes easy to combine programs: the
output of one program becomes an input argument to another, in the sense of function
composition.

Functional programming is based on a simple computation model with three construc-


tions: variables, function definitions, and applications of a function to an argument.
This model is called the λ-calculus and it was introduced by Alonzo Church in 1932,
thus before the first computer. It was created to offer a general theoretical model of
the notion of computability. In the λ-calculus, all functions are values which can be
manipulated. They can be used as arguments to other functions, or returned as the
result of a call to another function. The theory of λ-calculus asserts that everything
which is computable (i.e., programmable) can be written in this formalism. Its syntax
is too limited to make its use as a programming language practical, so primitive values
(such as integers or character strings), operations on these primitive values, control
structures, and declarations which allow the naming of values or functions and, in
particular, recursive functions, have all been added to the λ-calculus to make it more
palatable.
There are several classifications of functional languages. For our part, we will distin-
guish them according to two characteristics which seem to us most salient:
• Without side effects (pure) or with side effects (impure): a pure functional lan-
guage is a language in which there is no change of state. There everything is
simply a computation and the way it is carried out is unimportant. Impure func-
12 Chapter 2 : Functional programming

tional languages, such as Lisp or ML, integrate imperative traits such as change
of state. They permit the writing of algorithms in a style closer to languages like
Fortran, where the order of evaluation of expressions is significant.
• Dynamically typed or statically typed: typing permits verification of whether
an argument passed to a function is indeed of the type of the function’s formal
parameter. This verification can be made during program execution. In that case
this verification is called dynamic typing. If type errors occur the program will
halt in a consistent state. This is the case in the language Lisp. This verification
can also be done before program execution, that is, at compilation time. This a
priori verification is called static typing. Having been carried out once and for all,
it won’t slow down program execution. This is the case in the ML language and
its dialects such as Objective Caml. Only correctly typed programs, i.e., those
accepted by the type verifier, will be able to be compiled and then executed.

Chapter outline
This chapter presents the basic elements of the functional part of the Objective Caml
language, namely its syntactic elements, its language of types and its exception mech-
anism. This will lead us to the development of a first example of a complete program.
The first section describes the core of the language, beginning with primitive values
and the functions which manipulate them. We then go on to structured values and to
function values. The basic control structures are introduced as well as local and global
value declarations. The second section deals with type definitions for the construction
of structured values and with pattern matching to access these structures. The third
section compares the inferred type of functions and their domain of definition, which
leads us to introduce the exception mechanism. The fourth section illustrates all these
notions put together, by describing a simple application: a desktop calculator.

Functional core of Objective Caml


Like all functional languages, Objective Caml is an expression oriented language, where
programming consists mainly of creating functions and applying them. The result of
the evaluation of one of these expressions is a value in the language and the execution
of a program is the evaluation of all the expressions which comprise it.

Primitive values, functions, and types


Integers and floating-point numbers, characters, character strings, and booleans are
predefined in Objective Caml.
Functional core of Objective Caml 13

Numbers
There are two kinds of numbers: integers1 of type int and floating-point numbers of
type float. Objective Caml follows the IEEE 754 standard2 for representing double-
precision floating-point numbers. The operations on integers and floating-point num-
bers are described in figure 2.1. Let us note that when the result of an integer operation
is outside the interval on which values of type int are defined, this does not produce
an error, but the result is an integer within the system’s interval of integers. In other
words, all integer operations are operations modulo the boundaries of the interval.

integer numbers floating-point numbers


+ addition +. addition
- subtraction and unary negation -. subtraction and unary negation
* multiplication *. multiplication
/ integer division /. division
mod remainder of integer division ** exponentiation
# 1 ;; # 2.0 ; ;
- : int = 1 - : float = 2
# 1 + 2 ;; # 1.1 +. 2.2 ; ;
- : int = 3 - : float = 3.3
# 9 / 2 ;; # 9.1 /. 2.2 ; ;
- : int = 4 - : float = 4.13636363636
# 11 mod 3 ; ; # 1. /. 0. ; ;
- : int = 2 - : float = inf
(* limits of the representation *) (* limits of the representation *)
(* of integers *) (* of floating-point numbers *)
# 2147483650 ; ; # 222222222222.11111 ; ;
- : int = 2 - : float = 222222222222

Figure 2.1: Operations on numbers.

Differences between integers and floating-point numbers Values having dif-


ferent types such as float and int can never be compared directly. But there are
functions for conversion (float of int and int of float) between one and the other.

# 2 = 2.0 ; ;
Characters 5-8:
This expression has type float but is here used with type int
# 3.0 = float of int 3 ; ;

1. In the interval [−230 , 230 − 1] on 32-bit machines and in the interval [−262 , 262 − 1] on 64-bit
machines
2. The floating point number m × 10n is represented with a 53-bit mantissa m and an exponent n in
the interval [−1022, 1023].
14 Chapter 2 : Functional programming

- : bool = true

In the same way, operations on floating-point numbers are distinct from those on
integers.

# 3 + 2 ;;
- : int = 5
# 3.0 +. 2.0 ; ;
- : float = 5
# 3.0 + 2.0 ; ;
Characters 0-3:
This expression has type float but is here used with type int
# sin 3.14159 ; ;
- : float = 2.65358979335e-06

An ill-defined computation, such as a division by zero, will raise an exception (see page
54) which interrupts the computation. Floating-point numbers have a representation
for infinite values (printed as Inf) and ill-defined computations (printed as NaN3 ). The
main functions on floating-point numbers are described in figure 2.2.

functions on floats trigonometric functions


ceil cos cosine
floor sin sine
sqrt square root tan tangent
exp exponential acos arccosine
log natural log asin arcsine
log10 log base 10 atan arctangent
# ceil 3.4 ; ; # sin 1.57078 ; ;
- : float = 4 - : float = 0.999999999867
# floor 3.4 ; ; # sin (asin 0.707) ; ;
- : float = 3 - : float = 0.707
# ceil (-.3.4) ; ; # acos 0.0 ; ;
- : float = -3 - : float = 1.57079632679
# floor (-.3.4) ; ; # asin 3.14 ; ;
- : float = -4 - : float = nan

Figure 2.2: Functions on floats.

3. Not a Number
Functional core of Objective Caml 15

Characters and Strings


Characters, type char, correspond to integers between 0 and 255 inclusive, following
the ASCII encoding for the first 128. The functions char of int and int of char
support conversion between integers and characters. Character strings, type string,
are sequences of characters of definite length (less than 224 − 6). The concatenation
operator is ^ . The functions int of string, string of int, string of float and
float of string carry out the various conversions between numbers and character
strings.
# ’B’ ; ;
- : char = ’B’
# int of char ’B’ ; ;
- : int = 66
# "is a string" ; ;
- : string = "is a string"
# (string of int 1987) ^ " is the year Caml was created" ; ;
- : string = "1987 is the year Caml was created"

Even if a string contains the characters of a number, it won’t be possible to use it in


operations on numbers without carrying out an explicit conversion.
# "1999" + 1 ; ;
Characters 1-7:
This expression has type string but is here used with type int
# (int of string "1999") + 1 ; ;
- : int = 2000
Numerous functions on character strings are gathered in the String module (see page
217).

Booleans
Booleans, of type bool, belong to a set consisting of two values: true and false. The
primitive operators are described in figure 2.3. For historical reasons, the “and” and
“or” operators each have two forms.

not negation
& synonym for &&
&& sequential and
or synonym for ||
|| sequential or

Figure 2.3: Operators on booleans.

# true ; ;
- : bool = true
# not true ; ;
- : bool = false
16 Chapter 2 : Functional programming

# true && false ; ;


- : bool = false
The operators && and ||, or their synonyms, evaluate their left argument and then,
depending on its value, evaluate their right argument. They can be rewritten in the
form of conditional constructs (see page 18).

= structural equality < less than


== physical equality > greater than
<> negation of = <= less than or equal to
!= negation of == >= greater than or equal to

Figure 2.4: Equality and comparison operators.

The equality and comparison operators are described in figure 2.4. They are polymor-
phic, i.e., they can be used to compare two integers as well as two character strings.
The only constraint is that their two operands must be of the same type (see page 28).

# 1<=118 && (1=2 || not(1=2)) ; ;


- : bool = true
# 1.0 <= 118.0 && (1.0 = 2.0 || not (1.0 = 2.0)) ; ;
- : bool = true
# "one" < "two" ; ;
- : bool = true
# 0 < ’0’ ; ;
Characters 4-7:
This expression has type char but is here used with type int

Structural equality tests the equality of two values by traversing their structure, whereas
physical equality tests whether the two values occupy the same region in memory. These
two equality operators return the same result for simple values: booleans, characters,
integers and constant constructors (page 45).

Floating-point numbers and character strings are con-


Warning
sidered structured values.

Unit
The unit type describes a set which possesses only a single element, denoted: ().
# () ; ;
- : unit = ()
This value will often be used in imperative programs (see chapter 3, page 67) for
functions which carry out side effects. Functions whose result is the value () simulate
the notion of procedure, which doesn’t exist in Objective Caml, just as the type void
does in the C language.
Functional core of Objective Caml 17

Cartesian product, tuple


Values of possibly different types can be gathered in pairs or more generally in tuples.
The values making up a tuple are separated by commas. The type constructor * in-
dicates a tuple. The type int * string is the type of pairs whose first element is an
integer (of type int) and whose second is a character string (of type string).
# ( 12 , "October" ) ; ;
- : int * string = 12, "October"
When there is no ambiguity, it can be written more simply:
# 12 , "October" ; ;
- : int * string = 12, "October"
The functions fst and snd allow access to the first and second elements of a pair.
# fst ( 12 , "October" ) ; ;
- : int = 12
# snd ( 12 , "October" ) ; ;
- : string = "October"
These two functions accept pairs whose components are of any type whatsoever. They
are polymorphic, in the same way as equality.
# fst; ;
- : ’a * ’b -> ’a = <fun>
# fst ( "October", 12 ) ; ;
- : string = "October"
The type int * char * string is that of triplets whose first element is of type int,
whose second is of type char, and whose third is of type string. Its values are written

# ( 65 , ’B’ , "ascii" ) ; ;
- : int * char * string = 65, ’B’, "ascii"

The functions fst and snd applied to a tuple, other


Warning
than a pair, result in a type error.

# snd ( 65 , ’B’ , "ascii" ) ; ;


Characters 7-25:
This expression has type int * char * string but is here used with type
’a * ’b
There is indeed a difference between the type of a pair and that of a triplet. The type
int * int * int is different from the types (int * int) * int and int * (int *
int). Functions to access a triplet (and other tuples) are not defined by the core library.
One can use pattern matching to define them if need be (see page 34).

Lists
Values of the same type can be gathered into a list. A list can either be empty or
consist of elements of the same type.
# [] ; ;
- : ’a list = []
18 Chapter 2 : Functional programming

# [ 1 ; 2 ; 3 ] ;;
- : int list = [1; 2; 3]
# [ 1 ; "two" ; 3 ] ; ;
Characters 14-17:
This expression has type int list but is here used with type string list

The function which adds an element at the head of a list is the infix operator :: . It is
the analogue of Lisp’s cons.
# 1 :: 2 :: 3 :: [] ; ;
- : int list = [1; 2; 3]

Concatenation of two lists is also an infix operator @.


# [ 1 ] @ [ 2 ; 3 ] ;;
- : int list = [1; 2; 3]
# [ 1 ; 2 ] @ [ 3 ] ;;
- : int list = [1; 2; 3]

The other list manipulation functions are defined in the List library. The functions
hd and tl from this library give respectively the head and the tail of a list when these
values exist. These functions are denoted by List.hd and List.tl to indicate to the
system that they can be found in the module List4 .
# List.hd [ 1 ; 2 ; 3 ] ; ;
- : int = 1
# List.hd [] ; ;
Uncaught exception: Failure("hd")
In this last example, it is indeed problematic to request retrieval of the first element
of an empty list. It is for this reason that the system raises an exception (see page 54).

Conditional control structure


One of the indispensable control structures in any programming language is the struc-
ture called conditional (or branch) which guides the computation as a function of a
condition.
Syntax : if expr1 then expr2 else expr3

The expression expr1 is of type bool. The expressions expr2 and expr3 must be of the
same type, whatever it may be.

# if 3=4 then 0 else 4 ; ;


- : int = 4
# if 3=4 then "0" else "4" ; ;

4. The List module is presented on page 217.


Functional core of Objective Caml 19

- : string = "4"
# if 3=4 then 0 else "4"; ;
Characters 20-23:
This expression has type string but is here used with type int

A conditional construct is itself an expression and its evaluation returns a value.

# (if 3=5 then 8 else 10) + 5 ; ;


- : int = 15

Note
The else branch can be omitted, but in this case it is implicitly replaced
by else () . Consequently, the type of the expression expr2 must be unit
(see page 79).

Value declarations
A declaration binds a name to a value. There are two types: global declarations and
local declarations. In the first case, the declared names are known to all the expressions
following the declaration; in the second, the declared names are only known to one
expression. It is equally possible to simultaneously declare several name-value bindings.

Global declarations
Syntax : let name = expr ;;

A global declaration defines the binding between the name name and the value of the
expression expr which will be known to all subsequent expressions.
# let yr = "1999" ; ;
val yr : string = "1999"
# let x = int of string(yr) ; ;
val x : int = 1999
# x ;;
- : int = 1999
# x + 1 ;;
- : int = 2000
# let new yr = string of int (x + 1) ; ;
val new_yr : string = "2000"
20 Chapter 2 : Functional programming

Simultaneous global declarations

let name1 = expr1


and name2 = expr2
Syntax : ..
.
and namen = exprn ;;

A simultaneous declaration declares different symbols at the same level. They won’t
be known until the end of all the declarations.
# let x = 1 and y = 2 ; ;
val x : int = 1
val y : int = 2
# x + y ;;
- : int = 3
# let z = 3 and t = z + 2 ; ;
Characters 18-19:
Unbound value z

It is possible to gather several global declarations in the same phrase; then printing of
their types and their values does not take place until the end of the phrase, marked by
double “;;”. These declarations are evaluated sequentially, in contrast with a simulta-
neous declaration.
# let x = 2
let y = x + 3 ;;
val x : int = 2
val y : int = 5
A global declaration can be masked by a new declaration of the same name (see page
26).

Local declarations
Syntax : let name = expr1 in expr2 ;;

The name name is only known during the evaluation of expr2 . The local declaration
binds it to the value of expr1 .
# let xl = 3 in xl * xl ; ;
- : int = 9
The local declaration binding xl to the value 3 is only in effect during the evaluation
of xl * xl.
# xl ; ;
Characters 1-3:
Unbound value xl
A local declaration masks all previous declarations of the same name, but the previous
value is reinstated upon leaving the scope of the local declaration:
# let x = 2 ; ;
Functional core of Objective Caml 21

val x : int = 2
# let x = 3 in x * x ; ;
- : int = 9
# x * x ;;
- : int = 4
A local declaration is an expression and can thus be used to construct other expressions:

# (let x = 3 in x * x) + 1 ; ;
- : int = 10

Local declarations can also be simultaneous.

let name1 = expr1


and name2 = expr2
Syntax : ..
.
and namen = exprn
in expr ;;

# let a = 3.0 and b = 4.0 in sqrt (a*.a +. b*.b) ; ;


- : float = 5
# b ;;
Characters 0-1:
Unbound value b

Function expressions, functions


A function expression consists of a parameter and a body. The formal parameter is a
variable name and the body an expression. The parameter is said to be abstract. For
this reason, a function expression is also called an abstraction.
Syntax : function p –> expr

Thus the function which squares its argument is written:


# function x → x*x ; ;
- : int -> int = <fun>
The Objective Caml system deduces its type. The function type int -> int indicates
a function expecting a parameter of type int and returning a value of type int.
Application of a function to an argument is written as the function followed by the
argument.
# (function x → x * x) 5 ; ;
- : int = 25
The evaluation of an application amounts to evaluating the body of the function, here
22 Chapter 2 : Functional programming

x * x, where the formal parameter, x, is replaced by the value of the argument (or the
actual parameter), here 5.
In the construction of a function expression, expr is any expression whatsoever. In
particular, expr may itself be a function expression.

# function x → (function y → 3*x + y) ; ;


- : int -> int -> int = <fun>

The parentheses are not required. One can write more simply:
# function x → function y → 3*x + y ; ;
- : int -> int -> int = <fun>
The type of this expression can be read in the usual way as the type of a function which
expects two integers and returns an integer value. But in the context of a functional
language such as Objective Caml we are dealing more precisely with the type of a
function which expects an integer and returns a function value of type int -> int:
# (function x → function y → 3*x + y) 5 ; ;
- : int -> int = <fun>

One can, of course, use the function expression in the usual way by applying it to two
arguments. One writes:
# (function x → function y → 3*x + y) 4 5 ; ;
- : int = 17
When one writes f a b, there is an implicit parenthesization on the left which makes
this expression equivalent to: (f a) b.
Let’s examine the application

(function x → function y → 3*x + y) 4 5

in detail. To compute the value of this expression, it is necessary to compute the value
of

(function x → function y → 3*x + y) 4

which is a function expression equivalent to

function y → 3*4 + y

obtained by replacing x by 4 in 3*x + y. Applying this value (which is a function) to


5 we get the final value 3*4+5 = 17:
# (function x → function y → 3*x + y) 4 5 ; ;
- : int = 17
Functional core of Objective Caml 23

Arity of a function
The number of arguments of a function is called its arity. Usage inherited from math-
ematics demands that the arguments of a function be given in parentheses after the
name of the function. One writes: f (4, 5). We’ve just seen that in Objective Caml, one
more usually writes: f 4 5. One can, of course, write a function expression in Objective
Caml which can be applied to (4, 5):
# function (x,y) → 3*x + y ; ;
- : int * int -> int = <fun>
But, as its type indicates, this last expression expects not two, but only one argument:
a pair of integers. Trying to pass two arguments to a function which expects a pair or
trying to pass a pair to a function which expects two arguments results in a type error:

# (function (x,y) → 3*x + y) 4 5 ; ;


Characters 29-30:
This expression has type int but is here used with type int * int
# (function x → function y → 3*x + y) (4, 5) ; ;
Characters 39-43:
This expression has type int * int but is here used with type int

Alternative syntax
There is a more compact way of writing function expressions with several parameters.
It is a legacy of former versions of the Caml language. Its form is as follows:
Syntax : fun p1 . . . pn –> expr

It allows one to omit repetitions of the function keyword and the arrows. It is equiv-
alent to the following translation:

function p1 –> . . . –> function pn –> expr

# fun x y → 3*x + y ; ;
- : int -> int -> int = <fun>
# (fun x y → 3*x + y) 4 5 ; ;
- : int = 17
This form is still encountered often, in particular in the libraries provided with the
Objective Caml distribution.

Closure
Objective Caml treats a function expression like any other expression and is able to
compute its value. The value returned by the computation is a function expression and
is called a closure. Every Objective Caml expression is evaluated in an environment
24 Chapter 2 : Functional programming

consisting of name-value bindings coming from the declarations preceding the expres-
sion being computed. A closure can be described as a triplet consisting of the name
of the formal parameter, the body of the function, and the environment of the expres-
sion. This environment needs to be preserved because the body of a function expression
may use, in addition to the formal parameters, every other variable declared previously.
These variables are said to be “free” in the function expression. Their values will be
needed when the function expression is applied.
# let m = 3 ; ;
val m : int = 3
# function x → x + m ; ;
- : int -> int = <fun>
# (function x → x + m) 5 ; ;
- : int = 8

When application of a closure to an argument returns a new closure, the latter pos-
sesses within its environment all the bindings necessary for a future application. The
subsection on the scope of variables (see page 26) details this notion. We will return
to the memory representation of a closure in chapter 4 (page 103) as well as chapter
12 (page 332).
The function expressions used until now are anonymous. It is rather useful to be able
to name them.

Function value declarations


Function values are declared in the same way as other language values, by the let
construct.
# let succ = function x → x + 1 ; ;
val succ : int -> int = <fun>
# succ 420 ; ;
- : int = 421
# let g = function x → function y → 2*x + 3*y ; ;
val g : int -> int -> int = <fun>
# g 1 2; ;
- : int = 8

To simplify writing, the following notation is allowed:


Syntax : let name p1 . . . pn = expr

which is equivalent to the following form:

let name = function p1 –> . . . –> function pn –> expr

The following declarations of succ and g are equivalent to their previous declaration.
# let succ x = x + 1 ; ;
Functional core of Objective Caml 25

val succ : int -> int = <fun>


# let g x y = 2*x + 3*y ; ;
val g : int -> int -> int = <fun>

The completely functional character of Objective Caml is brought out by the following
example, in which the function h1 is obtained by the application of g to a single integer.
In this case one speaks of partial application:
# let h1 = g 1 ; ;
val h1 : int -> int = <fun>
# h1 2 ; ;
- : int = 8

One can also, starting from g, define a function h2 by fixing the value of the second
parameter, y, of g:
# let h2 = function x → g x 2 ; ;
val h2 : int -> int = <fun>
# h2 1 ; ;
- : int = 8

Declaration of infix functions


Certain functions taking two arguments can be applied in infix form. This is the case
with addition of integers. One writes 3 + 5 for the application of + to 3 and 5. To
use the symbol + as a regular function value, this must be syntactically indicated by
surrounding the infix symbol with parentheses. The syntax is as follows:

Syntax : ( op )

The following example defines the function succ using ( + ).


# ( + ) ;;
- : int -> int -> int = <fun>
# let succ = ( + ) 1 ; ;
val succ : int -> int = <fun>
# succ 3 ; ;
- : int = 4

It is also possible to define new operators. We define an operator ++, addition on pairs
of integers
# let ( ++ ) c1 c2 = (fst c1)+(fst c2), (snd c1)+(snd c2) ; ;
val ++ : int * int -> int * int -> int * int = <fun>
# let c = (2,3) ; ;
val c : int * int = 2, 3
# c ++ c ; ;
- : int * int = 4, 6
26 Chapter 2 : Functional programming

There is an important limitation on the possible operators. They must contain only
symbols (such as *, +, @, etc. ) and not letters or digits. Certain functions predefined as
infixes are exceptions to the rule. They are listed as follows: or mod land lor lxor
lsl lsr asr.

Higher order functions


A function value (a closure) can be returned as a result. It can equally well be passed as
an argument to a function. Functions taking function values as arguments or returning
them as results are called higher order.
# let h = function f → function y → (f y) + y ; ;
val h : (int -> int) -> int -> int = <fun>

Note
Application is implicitly parenthesized to the left, but function types are
implicitly parenthesized to the right. Thus the type of the function h can
be written
(int -> int) -> int -> int or (int -> int) -> (int -> int)

Higher order functions offer elegant possibilities for dealing with lists. For example the
function List.map can apply a function to all the elements of a list and return the
results in a list.
# List.map ; ;
- : (’a -> ’b) -> ’a list -> ’b list = <fun>
# let square x = string of int (x*x) ; ;
val square : int -> string = <fun>
# List.map square [1; 2; 3; 4] ; ;
- : string list = ["1"; "4"; "9"; "16"]

As another example, the function List.for all can find out whether all the elements
of a list satisfy a given criterion.
# List.for all ; ;
- : (’a -> bool) -> ’a list -> bool = <fun>
# List.for all (function n → n<>0) [-3; -2; -1; 1; 2; 3] ; ;
- : bool = true
# List.for all (function n → n<>0) [-3; -2; 0; 1; 2; 3] ; ;
- : bool = false

Scope of variables
In order for it to be possible to evaluate an expression, all the variables appearing
therein must be defined. This is the case in particular for the expression e in the dec-
Functional core of Objective Caml 27

laration let p = e. But since p is not yet known within this expression, this variable
can only be present if it refers to another value issued by a previous declaration.
# let p = p ^ "-suffix" ; ;
Characters 9-10:
Unbound value p
# let p = "prefix" ; ;
val p : string = "prefix"
# let p = p ^ "-suffix" ; ;
val p : string = "prefix-suffix"

In Objective Caml, variables are statically bound. The environment used to execute
the application of a closure is the one in effect at the moment of its declaration (static
scope) and not the one in effect at the moment of application (dynamic scope).

# let p = 10 ; ;
val p : int = 10
# let k x = (x, p, x+p) ; ;
val k : int -> int * int * int = <fun>
# k p ;;
- : int * int * int = 10, 10, 20
# let p = 1000 ; ;
val p : int = 1000
# k p ;;
- : int * int * int = 1000, 10, 1010
The function k contains a free variable: p. Since the latter is defined in the global
environment, the definition of k is legal. The binding between the name p and the
value 10 in the environment of the closure k is static, i.e., does not depend on the most
recent definition of p.

Recursive declarations
A variable declaration is called recursive if it uses its own identifier in its definition.
This facility is used mainly for functions, notably to simulate a definition by recurrence.
We have just seen that the let declaration does not support this. To declare a recursive
function we will use a dedicated syntactic construct.
Syntax : let rec name = expr ;;

We can equally well use the syntactic facility for defining function values while indi-
cating the function parameters:
Syntax : let rec name p1 . . . pn = expr ;;

By way of example, here is the function sigma which computes the sum of the (non-
negative) integers between 0 and the value of its argument, inclusive.
# let rec sigma x = if x = 0 then 0 else x + sigma (x-1) ; ;
val sigma : int -> int = <fun>
28 Chapter 2 : Functional programming

# sigma 10 ; ;
- : int = 55
It may be noted that this function does not terminate if its argument is strictly negative.
A recursive value is in general a function. The compiler rejects some recursive decla-
rations whose values are not functions:
# let rec x = x + 1 ; ;
Characters 13-18:
This kind of expression is not allowed as right-hand side of ‘let rec’
We will see however that in certain cases such declarations are allowed (see page 52).
The let rec declaration may be combined with the and construction for simultaneous
declarations. In this case, all the functions defined at the same level are known within
the bodies of each of the others. This permits, among other things, the declaration of
mutually recursive functions.
# let rec even n = (n<>1) && ((n=0) or (odd (n-1)))
and odd n = (n<>0) && ((n=1) or (even (n-1))) ;;
val even : int -> bool = <fun>
val odd : int -> bool = <fun>
# even 4 ; ;
- : bool = true
# odd 5 ; ;
- : bool = true

In the same way, local declarations can be recursive. This new definition of sigma tests
the validity of its argument before carrying out the computation of the sum defined by
a local function sigma rec.
# let sigma x =
let rec sigma rec x = if x = 0 then 0 else x + sigma rec (x-1) in
if (x<0) then "error: negative argument"
else "sigma = " ^ (string of int (sigma rec x)) ; ;
val sigma : int -> string = <fun>

Note
The need to give a return value of the same type, whether the argument is
negative or not, has forced us to give the result in the form of a character
string. Indeed, what value should be returned by sigma when its argument
is negative? We will see the proper way to manage this problem, using
exceptions (see page 54).

Polymorphism and type constraints


Some functions execute the same code for arguments having different types. For exam-
ple, creation of a pair from two values doesn’t require different functions for each type
Functional core of Objective Caml 29

known to the system5 . In the same way, the function to access the first field of a pair
doesn’t have to be differentiated according to the type of the value of this first field.
# let make pair a b = (a,b) ; ;
val make_pair : ’a -> ’b -> ’a * ’b = <fun>
# let p = make pair "paper" 451 ; ;
val p : string * int = "paper", 451
# let a = make pair ’B’ 65 ; ;
val a : char * int = ’B’, 65
# fst p ; ;
- : string = "paper"
# fst a ; ;
- : char = ’B’

Functions are called polymorphic if their return value or one of their parameters is of
a type which need not be specified. The type synthesizer contained in the Objective
Caml compiler finds the most general type for each expression. In this case, Objective
Caml uses variables, here ’a and ’b, to designate these general types. These variables
are instantiated to the type of the argument during application of the function.

With Objective Caml’s polymorphic functions, we get the advantages of being able
to write generic code usable for values of every type, while still preserving the exe-
cution safety of static typing. Indeed, although make pair is polymorphic, the value
created by (make pair ’B’ 65) has a well-specified type which is different from that of
(make pair "paper" 451). Moreover, type verification is carried out on compilation,
so the generality of the code does not hamper the efficiency of the program.

Examples of polymorphic functions and values


The following examples of polymorphic functions have functional parameters whose
type is parameterized.

The app function applies a function to an argument.


# let app = function f → function x → f x ; ;
val app : (’a -> ’b) -> ’a -> ’b = <fun>
So it can be applied to the function odd defined previously:
# app odd 2; ;
- : bool = false

The identity function (id ) takes a parameter and returns it as is.


# let id x = x ; ;
val id : ’a -> ’a = <fun>
# app id 1 ; ;
- : int = 1

5. Fortunately since the number of types is only limited by machine memory


30 Chapter 2 : Functional programming

The compose function takes two functions and another value and composes the appli-
cation of these two functions to this value.
# let compose f g x = f (g x) ; ;
val compose : (’a -> ’b) -> (’c -> ’a) -> ’c -> ’b = <fun>
# let add1 x = x+1 and mul5 x = x*5 in compose mul5 add1 9 ; ;
- : int = 50
It can be seen that the result of g must be of the same type as the argument of f.
Values other than functions can be polymorphic as well. For example, this is the case
for the empty list:
# let l = [] ; ;
val l : ’a list = []

The following example demonstrates that type synthesis indeed arises from resolution
of the constraints coming from function application and not from the value obtained
upon execution.
# let t = List.tl [2] ; ;
val t : int list = []
The type of List.tl is ’a list -> ’a list, so this function applied to a list of
integers returns a list of integers. The fact that upon execution it is the empty list
which is obtained doesn’t change its type at all.
Objective Caml generates parameterized types for every function which doesn’t use
the form of its arguments. This polymorphism is called parametric polymorphism6 .

Type constraint
As the Caml type synthesizer generates the most general type, it may be useful or
necessary to specify the type of an expression.

The syntactic form of a type constraint is as follows:

Syntax : ( expr : t )

When it runs into such a constraint, the type synthesizer will take it into account while
constructing the type of the expression. Using type constraints lets one:
• make the type of the parameters of a function visible;
• forbid the use of a function outside its intended context;
• specify the type of an expression, which will be particularly useful for mutable
values (see page 68).
The following examples demonstrate the use of such type constraints
# let add (x:int) (y:int) = x + y ; ;

6. Some predefined functions do not obey this rule, in particular the structural equality function (=)
which is polymorphic (its type is ’a -> ’a -> bool) but which explores the structure of its arguments
to test their equality.
Functional core of Objective Caml 31

val add : int -> int -> int = <fun>


# let make pair int (x:int) (y:int) = x,y; ;
val make_pair_int : int -> int -> int * int = <fun>
# let compose fn int (f : int → int) (g : int → int) (x:int) =
compose f g x; ;
val compose_fn_int : (int -> int) -> (int -> int) -> int -> int = <fun>
# let nil = ( [] : string list); ;
val nil : string list = []
# ’H’ :: nil; ;
Characters 5-8:
This expression has type string list but is here used with type char list

Restricting polymorphism this way lets us control the type of an expression better by
constraining the polymorphism of the type deduced by the system. Any defined type
whatsoever may be used, including ones containing type variables, as the following
example shows:
# let llnil = ( [] : ’a list list) ; ;
val llnil : ’a list list = []
# [1;2;3]:: llnil ; ;
- : int list list = [[1; 2; 3]]
The symbol llnil is a list of lists of any type whatsoever.
Here we are dealing with constraints, and not replacing Objective Caml’s type synthesis
with explicit typing. In particular, one cannot generalize types beyond what inference
permits.
# let add general (x:’a) (y:’b) = add x y ; ;
val add_general : int -> int -> int = <fun>

Type constraints will be used in module interfaces (see chapter 14) as well as in class
declarations (see chapter 15).

Examples
In this section we will give several somewhat elaborate examples of functions. Most of
these functions are predefined in Objective Caml. We will redefine them for the sake
of “pedagogy”.
Here, the test for the terminal case of recursive functions is implemented by a condi-
tional. Hence a programming style closer to Lisp. We will see how to give a more ML
character to these definitions when we present another way of defining functions by
case (see page 34).

Length of a list
Let’s start with the function null which tests whether a list is empty.
# let null l = (l = [] ) ; ;
32 Chapter 2 : Functional programming

val null : ’a list -> bool = <fun>


Next, we define the function size to compute the length of a list (i.e., the number of
its elements).
# let rec size l =
if null l then 0
else 1 + (size (List.tl l)) ; ;
val size : ’a list -> int = <fun>
# size [] ; ;
- : int = 0
# size [1;2;18;22] ; ;
- : int = 4
The function size tests whether the list argument is empty. If so it returns 0, if not it
returns 1 plus the value resulting from computing the length of the tail of the list.

Iteration of composition
The expression iterate n f computes the value f iterated n times.
# let rec iterate n f =
if n = 0 then (function x → x)
else compose f (iterate (n-1) f) ; ;
val iterate : int -> (’a -> ’a) -> ’a -> ’a = <fun>
The iterate function tests whether n is 0, if yes it returns the identity function, if not
it composes f with the iteration of f n-1 times.

Using iterate, one can define exponentiation as iteration of multiplication.


# let rec power i n =
let i times = ( * ) i in
iterate n i times 1 ; ;
val power : int -> int -> int = <fun>
# power 2 8 ; ;
- : int = 256
The power function iterates n times the function expression i times, then applies this
result to 1, which does indeed compute the nth power of an integer.

Multiplication table
We want to write a function multab which computes the multiplication table of an
integer passed as an argument.
First we define the function apply fun list such that, if f list is a list of functions,
apply fun list x f list returns the list of results of applying each element of f list
to x.
# let rec apply fun list x f list =
if null f list then []
else ((List.hd f list) x) :: (apply fun list x (List.tl f list)) ; ;
val apply_fun_list : ’a -> (’a -> ’b) list -> ’b list = <fun>
# apply fun list 1 [( + ) 1;( + ) 2;( + ) 3] ; ;
Functional core of Objective Caml 33

- : int list = [2; 3; 4]

The function mk mult fun list returns the list of functions multiplying their argument
by i, for i varying from 0 to n.
# let mk mult fun list n =
let rec mmfl aux p =
if p = n then [ ( * ) n ]
else (( * ) p) :: (mmfl aux (p+1))
in (mmfl aux 1) ; ;
val mk_mult_fun_list : int -> (int -> int) list = <fun>

We obtain the multiplication table of 7 by:


# let multab n = apply fun list n (mk mult fun list 10) ; ;
val multab : int -> int list = <fun>
# multab 7 ; ;
- : int list = [7; 14; 21; 28; 35; 42; 49; 56; 63; 70]

Iteration over lists


The function call fold left f a [e1; e2; ... ; en] returns f ... (f (f a e1) e2)
... en. So there are n applications.
# let rec fold left f a l =
if null l then a
else fold left f ( f a (List.hd l)) (List.tl l) ; ;
val fold_left : (’a -> ’b -> ’a) -> ’a -> ’b list -> ’a = <fun>

The function fold left permits the compact definition of a function to compute the
sum of the elements of a list of integers:
# let sum list = fold left (+) 0 ; ;
val sum_list : int list -> int = <fun>
# sum list [2;4;7] ; ;
- : int = 13

Or else, the concatenation of the elements of a list of strings:


# let concat list = fold left (^) "" ; ;
val concat_list : string list -> string = <fun>
# concat list ["Hello "; "world" ; "!"] ; ;
- : string = "Hello world!"
34 Chapter 2 : Functional programming

Type declarations and pattern matching


Although Objective Caml’s predefined types permit the construction of data structures
from tuples and lists, one needs to be able to define new types to describe certain data
structures. In Objective Caml, type declarations are recursive and may be parameter-
ized by type variables, in the same vein as the type ’a list already encountered. Type
inference takes these new declarations into account to produce the type of an expres-
sion. The construction of values of these new types uses the constructors described in
their definition. A special feature of languages in the ML family is pattern matching. It
allows simple access to the components of complex data structures. A function defini-
tion most often corresponds to pattern matching over one of its parameters, allowing
the function to be defined by cases.
First of all we present pattern matching over the predefined types, and then go on to
describe the various ways to declare structured types and how to construct values of
such types, as well as how to access their components through pattern matching.

Pattern matching
A pattern is not strictly speaking an Objective Caml expression. It’s more like a correct
(syntactically, and from the point of view of types) arrangement of elements such as
constants of the primitive types (int, bool, char, ..), variables, constructors, and the
symbol called the wildcard pattern. Other symbols are used in writing patterns. We
will introduce them to the extent needed.
Pattern matching applies to values. It is used to recognize the form of this value and lets
the computation be guided accordingly, associating with each pattern an expression to
compute.

match expr with


| p1 –> expr1
Syntax : ..
.
| pn –> exprn

The expression expr is matched sequentially to the various patterns p1 , . . . , pn . If one of


the patterns (for example pi ) is consistent with the value of expr then the corresponding
computation branch (expri ) is evaluated. The various patterns pi are of the same type.
The same goes for the various expressions expri . The vertical bar preceding the first
pattern is optional.

Examples
Here are two ways to define by pattern matching a function imply of type (bool *
bool) –> bool implementing logical implication. A pattern which matches pairs has
the form ( , ).
Type declarations and pattern matching 35

The first version of imply enumerates all possible cases, as a truth table would:
# let imply v = match v with
(true,true) → true
| (true,false) → false
| (false,true) → true
| (false,false) → true; ;
val imply : bool * bool -> bool = <fun>

By using variables which group together several cases, we obtain a more compact
definition.
# let imply v = match v with
(true,x) → x
| (false,x) → true; ;
val imply : bool * bool -> bool = <fun>
These two versions of imply compute the same function. That is, they return the same
values for the same inputs.

Linear pattern
A pattern must necessarily be linear, that is, no given variable can occur more than
once inside the pattern being matched. Thus, we might have hoped to be able to write:

# let equal c = match c with


(x,x) → true
| (x,y) → false; ;
Characters 35-36:
This variable is bound several times in this matching
But this would have required the compiler to know how to carry out equality tests.
Yet this immediately raises numerous problems. If we accept physical equality between
values, we get a system which is too weak, incapable of recognizing the equality be-
tween two occurrences of the list [1; 2], for example. If we decide to use structural
equality, we run the risk of having to traverse, ad infinitum, circular structures. Re-
cursive functions, for example, are circular structures, but we can construct recursive,
hence circular, values which are not functions as well (see page 52).

Wildcard pattern
The symbol matches all possible values. It is called a wildcard pattern. It can be used
to match complex types. We use it, for example, to further simplify the definition of
the function imply:
# let imply v = match v with
(true,false) → false
| _ → true; ;
val imply : bool * bool -> bool = <fun>
36 Chapter 2 : Functional programming

A definition by pattern matching must handle the entire set of possible cases of the
values being matched. If this is not the case, the compiler prints a warning message:
# let is zero n = match n with 0 → true ; ;
Characters 17-40:
Warning: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
1
val is_zero : int -> bool = <fun>

Indeed if the actual parameter is different from 0 the function doesn’t know what value
to return. So the case analysis can be completed using the wildcard pattern.
# let is zero n = match n with
0 → true
| _ → false ; ;
val is_zero : int -> bool = <fun>

If, at run-time, no pattern is selected, then an exception is raised. Thus, one can write:

# let f x = match x with 1 → 3 ; ;


Characters 11-30:
Warning: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
0
val f : int -> int = <fun>
# f 1 ;;
- : int = 3
# f 4 ;;
Uncaught exception: Match_failure("", 11, 30)
The Match Failure exception is raised by the call to f 4, and if it is not handled
induces the computation in progress to halt (see 54)

Combining patterns
Combining several patterns lets us obtain a new pattern which can match a value
according to one or another of the original patterns. The syntactic form is as follows:

Syntax : p1 | . . . | pn

It constructs a new pattern by combining the patterns p1 , . . . and pn . The only strong
constraint is that all naming is forbidden within these patterns. So each one of them
must contain only constant values or the wildcard pattern. The following example
demonstrates how to verify that a character is a vowel.
# let is a vowel c = match c with
’a’ | ’e’ | ’i’ | ’o’ | ’u’ | ’y’ → true
| _ → false ; ;
val is_a_vowel : char -> bool = <fun>
Type declarations and pattern matching 37

# is a vowel ’i’ ; ;
- : bool = true
# is a vowel ’j’ ; ;
- : bool = false

Pattern matching of a parameter


Pattern matching is used in an essential way for defining functions by cases. To make
writing these definitions easier, the syntactic construct function allows pattern match-
ing of a parameter:

function | p1 –> expr1


| p2 –> expr2
Syntax : ..
.
| pn –> exprn

The vertical bar preceding the first pattern is optional here as well. In fact, like Mr.
Jourdain, each time we define a function, we use pattern matching7 . Indeed, the con-
struction function x –> expression, is a definition by pattern matching using a
single pattern reduced to one variable. One can make use of this detail with simple
patterns as in:
# let f = function (x,y) → 2*x + 3*y + 4 ; ;
val f : int * int -> int = <fun>

In fact the form

function p1 –> expr1 | . . . | pn –> exprn

is equivalent to

function expr –> match expr with p1 –> expr1 | . . . | pn –> exprn

Using the equivalence of the declarations mentioned on page 24, we write:


# let f (x,y) = 2*x + 3*y + 4 ; ;
val f : int * int -> int = <fun>
But this natural way of writing is only possible if the value being matched belongs to

7. Translator’s note: In Molière’s play Le Bourgeois Gentilhomme (The Bourgeois Gentleman), the
character Mr. Jourdain is amazed to discover that he has been speaking prose all his life. The play
can be found at
Link: http://www.site-moliere.com/pieces/bourgeoi.htm
and
Link: http://moliere-in-english.com/bourgeois.html
gives an excerpt from an English translation, including this part.
38 Chapter 2 : Functional programming

a type having only a single constructor. If such is not the case, the pattern matching
is not exhaustive:
# let is zero 0 = true ; ;
Characters 13-21:
Warning: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
1
val is_zero : int -> bool = <fun>

Naming a value being matched


During pattern matching, it is sometimes useful to name part or all of the pattern. The
following syntactic form introduces the keyword as which binds a name to a pattern.

Syntax : ( p as name )

This is useful when one needs to take apart a value while still maintaining its integrity.
In the following example, the function min rat gives the smaller rational of a pair of
rationals. The latter are each represented by a numerator and denominator in a pair.

# let min rat pr = match pr with


((_,0),p2) → p2
| (p1,(_,0)) → p1
| (((n1,d1) as r1), ((n2,d2) as r2)) →
if (n1 * d2 ) < (n2 * d1) then r1 else r2; ;
val min_rat : (int * int) * (int * int) -> int * int = <fun>
To compare two rationals, it is necessary to take them apart in order to name their
numerators and denominators (n1, n2, d1 and d2), but the initial pair (r1 or r2) must
be returned. The as construct allows us to name the parts of a single value in this way.
This lets us avoid having to reconstruct the rational returned as the result.

Pattern matching with guards


Pattern matching with guards corresponds to the evaluation of a conditional expression
immediately after the pattern is matched. If this expression comes back true, then
the expression associated with that pattern is evaluated, otherwise pattern matching
continues with the following pattern.

match expr with


..
.
Syntax :
| pi when condi –> expri
..
.

The following example uses two guards to test equality of two rationals.
# let eq rat cr = match cr with
Type declarations and pattern matching 39

((_,0),(_,0)) → true
| ((_,0),_) → false
| (_,(_,0)) → false
| ((n1,1), (n2,1)) when n1 = n2 → true
| ((n1,d1), (n2,d2)) when ((n1 * d2) = (n2 * d1)) → true
| _ → false; ;
val eq_rat : (int * int) * (int * int) -> bool = <fun>
If the guard fails when the fourth pattern is matched, matching continues with the
fifth pattern.
Note
The verification carried out by Objective Caml as to whether the pattern
matching is exhaustive assumes that the conditional expression in the
guard may be false. Consequently, it does not count this pattern since it is
not possible to know, before execution, whether the guard will be satisfied
or not.
It won’t be possible to detect that the pattern matching in the following example is
exhaustive.
# let f = function x when x = x → true; ;
Characters 10-40:
Warning: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
_
val f : ’a -> bool = <fun>

Pattern matching on character intervals


In the context of pattern matching on characters, it is tedious to construct the combi-
nation of all the patterns corresponding to a character interval. Indeed, if one wishes
to test a character or even a letter, one would need to write 26 patterns at a minimum
and combine them. For characters, Objective Caml permits writing patterns of the
form:
Syntax : ’c1 ’ .. ’cn ’
It is equivalent to the combination: ’c1 ’ | ’c2 ’ | ...| ’cn ’.
For example the pattern ’0’ .. ’9’ corresponds to the pattern ’0’ | ’1’ | ’2’
| ’3’ | ’4’ | ’5’ | ’6’ | ’7’ | ’8’ | ’9’. The first form is nicer to read and
quicker to write.

This feature is among the extensions to the language


Warning
and may change in future versions.
Using combined patterns and intervals, we define a function categorizing characters
according to several criteria.
# let char discriminate c = match c with
40 Chapter 2 : Functional programming

’a’ | ’e’ | ’i’ | ’o’ | ’u’ | ’y’


| ’A’ | ’E’ | ’I’ | ’O’ | ’U’ | ’Y’ → "Vowel"
| ’a’..’z’ | ’A’..’Z’ → "Consonant"
| ’0’..’9’ → "Digit"
| _ → "Other" ; ;
val char_discriminate : char -> string = <fun>
It should be noted that the order of the groups of patterns has some significance.
Indeed, the second set of patterns includes the first, but it is not examined until after
the check on the first.

Pattern matching on lists


As we have seen, a list can be:
• either empty (the list is of the form []),
• or composed of a first element (its head) and a sublist (its tail). The list is then
of the form h::t.
These two possible ways of writing a list can be used as patterns and allow pattern
matching on a list.
# let rec size x = match x with
[] → 0
| _::tail x → 1 + (size tail x) ; ;
val size : ’a list -> int = <fun>
# size [] ; ;
- : int = 0
# size [7;9;2;6]; ;
- : int = 4

So we can redo the examples described previously (see page 31) using pattern matching,
such as iteration over lists for example.
# let rec fold left f a = function
[] → a
| head :: tail → fold left f (f a head) tail ; ;
val fold_left : (’a -> ’b -> ’a) -> ’a -> ’b list -> ’a = <fun>
# fold left (+) 0 [8;4;10]; ;
- : int = 22

Value declaration through pattern matching


Value declaration in fact uses pattern matching. The declaration let x = 18 matches
the value 18 with the pattern x. Any pattern is allowed as the left-hand side of a
declaration; the variables in the pattern are bound to the values which they match.
# let (a,b,c) = (1, true, ’A’); ;
val a : int = 1
Type declarations and pattern matching 41

val b : bool = true


val c : char = ’A’
# let (d,c) = 8, 3 in d + c; ;
- : int = 11
The scope of pattern variables is the usual static scope for local declarations. Here, c
remains bound to the value ’A’.
# a + (int of char c); ;
- : int = 66

As with any kind of pattern matching, value declaration may not be exhaustive.
# let [x;y;z] = [1;2;3]; ;
Characters 5-12:
Warning: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
[]
val x : int = 1
val y : int = 2
val z : int = 3
# let [x;y;z] = [1;2;3;4]; ;
Characters 4-11:
Warning: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
[]
Uncaught exception: Match_failure("", 4, 11)

Any pattern is allowed, including constructors, wildcards and combined patterns.


# let head :: 2 :: _ = [1; 2; 3] ; ;
Characters 5-19:
Warning: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
[]
val head : int = 1
# let _ = 3. +. 0.14 in "PI" ; ;
- : string = "PI"

This last example is of little use in the functional world insofar as the computed value
3.14 is not named and so is lost.

Type declaration
Type declarations are another possible ingredient in an Objective Caml phrase. They
support the definition of new types corresponding to the original data structures used
in a program. There are two major families of types: product types for tuples or records;
and sum types for unions.
42 Chapter 2 : Functional programming

Type declarations use the keyword type.

Syntax : type name = typedef ;;

In contrast with variable declarations, type declarations are recursive by default. That
is, type declarations, when combined, support the declaration of mutually recursive
types.

type name1 = typedef1


and name2 = typedef2
Syntax : ..
.
and namen = typedefn ;;

Type declarations can be parameterized by type variables. A type variable name always
begins with an apostrophe (the ’ character):

Syntax : type ’a name = typedef ;;

When there are several of them, the type parameters are declared as a tuple in front
of the name of the type:

Syntax : type (’a1 . . . ’an ) name = typedef ;;

Only the type parameters defined on the left-hand side of the declaration may appear
on the right-hand side.
Note
Objective Caml’s type printer renames the type parameters encountered;
the first is called ’a, the second ’b and so forth.
One can always define a new type from one or more existing types.
Syntax : type name = type expression

This is useful for constraining a type which one finds too general.
# type ’param paired with integer = int * ’param ; ;
type ’a paired_with_integer = int * ’a
# type specific pair = float paired with integer ; ;
type specific_pair = float paired_with_integer

Nevertheless without type constraints, inference will produce the most general type.
# let x = (3, 3.14) ; ;
val x : int * float = 3, 3.14

But one can use a type constraint to see the desired name appear:
# let (x:specific pair) = (3, 3.14) ; ;
val x : specific_pair = 3, 3.14
Type declarations and pattern matching 43

Records
Records are tuples, each of whose fields is named in the same way as the Pascal record
or the C struct. A record always corresponds to the declaration of a new type. A record
type is defined by the declaration of its name and the names and types of each of its
fields.
Syntax : type name = { name1 : t1 ; . . . ; namen : tn } ;;

We can define a type representing complex numbers by:


# type complex = { re:float; im:float } ; ;
type complex = { re: float; im: float }

The creation of a value of record type is done by giving a value to each of its fields (in
arbitrary order).

Syntax : { namei1 = expri1 ; . . . ; namein = exprin } ;;

For example, we create a complex number with real part 2. and imaginary part 3.:
# let c = {re=2.;im=3.} ; ;
val c : complex = {re=2; im=3}
# c = {im=3.;re=2.} ; ;
- : bool = true

In the case where some fields are missing, the following error is produced:
# let d = { im=4. } ; ;
Characters 9-18:
Some labels are undefined

A field can be accessed in two ways: by the dot notation or by pattern matching on
certain fields.
The dot notation syntax is as usual:
Syntax : expr.name

The expression expr must be of a record type containing a field name.


Pattern matching a record lets one retrieve the value bound to several fields. A pattern
to match a record has the following syntax:

Syntax : { namei = pi ; . . . ; namej = pj }

The patterns are to the right of the = sign (pi , . . . , pj ). It is not necessary to make all
the fields of a record appear in such a pattern.
44 Chapter 2 : Functional programming

The function add complex accesses fields through the dot notation, while the function
mult complex accesses them through pattern matching.
# let add complex c1 c2 = {re=c1.re+.c2.re; im=c1.im+.c2.im}; ;
val add_complex : complex -> complex -> complex = <fun>
# add complex c c ; ;
- : complex = {re=4; im=6}
# let mult complex c1 c2 = match (c1,c2) with
({re=x1;im=y1},{re=x2;im=y2}) → {re=x1*.x2-.y1*.y2;im=x1*.y2+.x2*.y1} ; ;
val mult_complex : complex -> complex -> complex = <fun>
# mult complex c c ; ;
- : complex = {re=-5; im=12}

The advantages of records, as opposed to tuples, are at least twofold:


• descriptive and distinguishing information thanks to the field names: in particular
this allows pattern matching to be simplified;
• access in an identical way, by name, to any field of the record whatsoever: the
order of the fields no longer has significance, only their names count.
The following example shows the ease of accessing the fields of records as opposed to
tuples:
# let a = (1,2,3) ; ;
val a : int * int * int = 1, 2, 3
# let f tr = match tr with x,_,_ → x ; ;
val f : ’a * ’b * ’c -> ’a = <fun>
# f a ;;
- : int = 1
# type triplet = {x1:int; x2:int; x3:int} ; ;
type triplet = { x1: int; x2: int; x3: int }
# let b = {x1=1; x2=2; x3=3} ; ;
val b : triplet = {x1=1; x2=2; x3=3}
# let g tr = tr.x1 ; ;
val g : triplet -> int = <fun>
# g b ;;
- : int = 1

For pattern matching, it is not necessary to indicate all the fields of the record being
matched. The inferred type is then that of the last field.
# let h tr = match tr with {x1=x} → x; ;
val h : triplet -> int = <fun>
# h b; ;
- : int = 1

There is a construction which lets one create a record identical to another except for
some fields. It is often useful for records containing many fields.
Type declarations and pattern matching 45

Syntax : { name with namei = expri ; . . . ; namej =exprj }

# let c = {b with x1=0} ; ;


val c : triplet = {x1=0; x2=2; x3=3}
A new copy of the value of b is created where only the field x1 has a new value.

This feature is among the extensions to the language


Warning
and may change in future versions.

Sum types
In contrast with tuples or records, which correspond to a Cartesian product, the dec-
laration of a sum type corresponds to a union of sets. Different types (for example
integers or character strings) are gathered into a single type. The various members of
the sum are distinguished by constructors, which support on the one hand, as their
name indicates, construction of values of this type and on the other hand, thanks to
pattern matching, access to the components of these values. To apply a constructor to
an argument is to indicate that the value returned belongs to this new type.
A sum type is declared by giving the names of its constructors and the types of their
eventual arguments.

type name = . . .
| Namei . . .
Syntax :
| Namej of tj . . .
| Namek of tk * ...* tl . . . ;;

A constructor name is a particular identifier:

The names of constructors always begin with a capital


Warning
letter.

Constant constructors
A constructor which doesn’t expect an argument is called a constant constructor. Con-
stant constructors can subsequently be used directly as a value in the language, as a
constant.
# type coin = Heads | Tails; ;
type coin = | Heads | Tails
# Tails; ;
- : coin = Tails
The type bool can be defined in this way.
46 Chapter 2 : Functional programming

Constructors with arguments


Constructors can have arguments. The keyword of indicates the type of the construc-
tor’s arguments. This supports the gathering into a single type of objects of different
types, each one being introduced with a particular constructor.
Here is a classic example of defining a datatype to represent the cards in a game, here
Tarot8 . The types suit and card are defined in the following way:
# type suit = Spades | Hearts | Diamonds | Clubs ; ;
# type card =
King of suit
| Queen of suit
| Knight of suit
| Knave of suit
| Minor card of suit * int
| Trump of int
| Joker ; ;

The creation of a value of type card is carried out through the application of a con-
structor to a value of the appropriate type.
# King Spades ; ;
- : card = King Spades
# Minor card(Hearts, 10) ; ;
- : card = Minor_card (Hearts, 10)
# Trump 21 ; ;
- : card = Trump 21

And here, for example, is the function all cards which constructs a list of all the
cards of a suit passed as a parameter.
# let rec interval a b = if a = b then [b] else a :: (interval (a+1) b) ; ;
val interval : int -> int -> int list = <fun>
# let all cards s =
let face cards = [ Knave s; Knight s; Queen s; King s ]
and other cards = List.map (function n → Minor card(s,n)) (interval 1 10)
in face cards @ other cards ; ;
val all_cards : suit -> card list = <fun>
# all cards Hearts ; ;
- : card list =
[Knave Hearts; Knight Hearts; Queen Hearts; King Hearts;
Minor_card (Hearts, 1); Minor_card (Hearts, 2); Minor_card (Hearts, 3);
Minor_card (Hearts, ...); ...]

8. Translator’s note: The rules for French Tarot can be found, for example, at
Link: http://www.pagat.com/tarot/frtarot.html
Type declarations and pattern matching 47

To handle values of sum types, we use pattern matching. The following example con-
structs conversion functions from values of type suit and of type card to character
strings (type string):
# let string of suit = function
Spades → "spades"
| Diamonds → "diamonds"
| Hearts → "hearts"
| Clubs → "clubs" ; ;
val string_of_suit : suit -> string = <fun>
# let string of card = function
King c → "king of " ^ (string of suit c)
| Queen c → "queen of " ^ (string of suit c)
| Knave c → "knave of " ^ (string of suit c)
| Knight c → "knight of " ^ (string of suit c)
| Minor card (c, n) → (string of int n) ^ " of "^(string of suit c)
| Trump n → (string of int n) ^ " of trumps"
| Joker → "joker" ; ;
val string_of_card : card -> string = <fun>
Lining up the patterns makes these functions easy to read.
The constructor Minor card is treated as a constructor with two arguments. Pattern
matching on such a value requires naming its two components.
# let is minor card c = match c with
Minor card v → true
| _ → false; ;
Characters 41-53:
The constructor Minor_card expects 2 argument(s),
but is here applied to 1 argument(s)

To avoid having to name each component of a constructor, one declares it to have a


single argument by parenthesizing the corresponding tuple type. The two constructors
which follow are pattern-matched differently.
# type t =
C of int * bool
| D of (int * bool) ; ;
# let access v = match v with
C (i, b) → i,b
| D x → x; ;
val access : t -> int * bool = <fun>

Recursive types
Recursive type definitions are indispensable in any algorithmic language for describing
the usual data structures (lists, heaps, trees, graphs, etc.). To this end, in Objective
Caml type definition is recursive by default, in contrast with value declaration (let).
48 Chapter 2 : Functional programming

Objective Caml’s predefined type of lists only takes a single parameter. One may wish
to store values of belonging to two different types in a list structure, for example,
integers (int) or characters (char). In this case, one defines:
# type int or char list =
Nil
| Int cons of int * int or char list
| Char cons of char * int or char list ; ;

# let l1 = Char cons ( ’=’, Int cons(5, Nil) ) in


Int cons ( 2, Char cons ( ’+’, Int cons(3, l1) ) ) ; ;
- : int_or_char_list =
Int_cons (2, Char_cons (’+’, Int_cons (3, Char_cons (’=’, Int_cons (...)))))

Parametrized types
A user can equally well declare types with parameters. This lets us generalize the
example of lists containing values of two different types.
# type (’a, ’b) list2 =
Nil
| Acons of ’a * (’a, ’b) list2
| Bcons of ’b * (’a, ’b) list2 ; ;

# Acons(2, Bcons(’+’, Acons(3, Bcons(’=’, Acons(5, Nil))))) ; ;


- : (int, char) list2 =
Acons (2, Bcons (’+’, Acons (3, Bcons (’=’, Acons (...)))))

One can, obviously, instantiate the parameters ’a and ’b with the same type.
# Acons(1, Bcons(2, Acons(3, Bcons(4, Nil)))) ; ;
- : (int, int) list2 = Acons (1, Bcons (2, Acons (3, Bcons (4, Nil))))

This use of the type list2 can, as in the preceding example, serve to mark even
integers and odd integers. In this way we extract the sublist of even integers in order
to construct an ordinary list.
# let rec extract odd = function
Nil → []
| Acons(_, x) → extract odd x
| Bcons(n, x) → n :: (extract odd x) ; ;
val extract_odd : (’a, ’b) list2 -> ’b list = <fun>
The definition of this function doesn’t give a single clue as to the nature of the values
stored in the structure. That is why its type is parameterized.
Type declarations and pattern matching 49

Scope of declarations
Constructor names obey the same scope discipline as global declarations: a redefini-
tion masks the previous one. Nevertheless values of the masked type still exist. The
interactive toplevel does not distinguish these two types in its output. Whence some
unclear error messages.
In this first example, the constant constructor Nil of type int or char has been
masked by the constructor declarations of the type (’a, ’b) list2.
# Int cons(0, Nil) ; ;
Characters 13-16:
This expression has type (’a, ’b) list2 but is here used with type
int_or_char_list

This second example provokes a rather baffling error message, at least the first time it
appears. Let the little program be as follows:
# type t1 = Empty | Full; ;
type t1 = | Empty | Full
# let empty t1 x = match x with Empty → true | Full → false ; ;
val empty_t1 : t1 -> bool = <fun>
# empty t1 Empty; ;
- : bool = true

Then, we redeclare the type t1:


# type t1 = {u : int; v : int} ; ;
type t1 = { u: int; v: int }
# let y = { u=2; v=3 } ; ;
val y : t1 = {u=2; v=3}

Now if we apply the function empty t1 to a value of the new type t1, we get the
following error message:
# empty t1 y; ;
Characters 10-11:
This expression has type t1 but is here used with type t1
The first occurrence of t1 represents the first type defined, while the second corresponds
to the second type.

Function types
The type of the argument of a constructor may be arbitrary. In particular, it may very
well contain a function type. The following type constructs lists, all of whose elements
except the last are function values.
# type ’a listf =
Val of ’a
| Fun of (’a → ’a) * ’a listf ; ;
50 Chapter 2 : Functional programming

type ’a listf = | Val of ’a | Fun of (’a -> ’a) * ’a listf

Since function values are values which can be manipulated in the language, we can
construct values of type listf:
# let eight div = (/) 8 ; ;
val eight_div : int -> int = <fun>
# let gl = Fun (succ, (Fun (eight div, Val 4))) ; ;
val gl : int listf = Fun (<fun>, Fun (<fun>, Val 4))
and functions which pattern-match such values:
# let rec compute = function
Val v → v
| Fun(f, x) → f (compute x) ; ;
val compute : ’a listf -> ’a = <fun>
# compute gl; ;
- : int = 3

Example: representing trees


Tree structures come up frequently in programming. Recursive types make it easy to
define and manipulate such structures. In this subsection, we give two examples of tree
structures.

Binary trees We define a binary tree structure whose nodes are labelled with values
of a single type by declaring:
# type ’a bin tree =
Empty
| Node of ’a bin tree * ’a * ’a bin tree ; ;

We use this structure to define a little sorting program using binary search trees. A
binary search tree has the property that all the values in the left branch are less than
that of the root, and all those of the right branch are greater. Figure 2.5 gives an
example of such a structure over the integers. The empty nodes (constructor Empty)
are represented there by little squares; the others (constructor Node), by a circle in
which is inscribed the stored value.
A sorted list is extracted from a binary search tree via an inorder traversal carried out
by the following function:

# let rec list of tree = function


Empty → []
| Node(lb, r, rb) → (list of tree lb) @ (r :: (list of tree rb)) ; ;
val list_of_tree : ’a bin_tree -> ’a list = <fun>
Type declarations and pattern matching 51

2 8

1 4 7 9

0 3 5

Figure 2.5: Binary search tree.

To obtain a binary search tree from a list, we define an insert function.


# let rec insert x = function
Empty → Node(Empty, x, Empty)
| Node(lb, r, rb) → if x < r then Node(insert x lb, r, rb)
else Node(lb, r, insert x rb) ; ;
val insert : ’a -> ’a bin_tree -> ’a bin_tree = <fun>

The function to transform a list into a tree is obtained by iterating the function insert.

# let rec tree of list = function


[] → Empty
| h :: t → insert h (tree of list t) ; ;
val tree_of_list : ’a list -> ’a bin_tree = <fun>

The sort function is then simply the composition of the functions tree of list and
list of tree.
# let sort x = list of tree (tree of list x) ; ;
val sort : ’a list -> ’a list = <fun>
# sort [5; 8; 2; 7; 1; 0; 3; 6; 9; 4] ; ;
- : int list = [0; 1; 2; 3; 4; 5; 6; 7; 8; 9]

General planar trees In this part, we use the following predefined functions from
the List module (see page 217):
• List.map: which applies a function to all the elements of a list and returns the
list of results;
52 Chapter 2 : Functional programming

• List.fold left: which is an equivalent version of the function fold left defined
on page 33;
• List.exists: which applies a boolean-valued function to all the elements of a
list; if one of these applications yields true then the result is true, otherwise the
function returns false.
A general planar tree is a tree whose number of branches is not fixed a priori; to each
node is associated a list of branches whose length may vary.
# type ’a tree = Empty
| Node of ’a * ’a tree list ; ;
The empty tree is represented by the value Empty. A leaf is a node without branches
either of the form Node(x,[]), or of the degenerate form Node(x, [Empty;Empty;
..]). It is then relatively easy to write functions to manipulate these trees, e.g., to
determine whether an element belongs to a tree or compute the height of the tree.
To test membership of an element e, we use the following algorithm: if the tree is empty
then e does not belong to this tree, otherwise e belongs to the tree if and only if either
it is equal to the label of the root, or it belongs to one of its branches.
# let rec belongs e = function
Empty → false
| Node(v, bs) → (e=v) or (List.exists (belongs e) bs) ; ;
val belongs : ’a -> ’a tree -> bool = <fun>

To compute the height of a tree, we use the following definition: an empty tree has
height 0, otherwise the height of the tree is equal to the height of its highest subtree
plus 1.
# let rec height =
let max list l = List.fold left max 0 l in
function
Empty → 0
| Node (_, bs) → 1 + (max list (List.map height bs)) ; ;
val height : ’a tree -> int = <fun>

Recursive values which are not functions


Recursive declaration of non-function values allows the construction of circular data
structures.
The following declaration constructs a circular list with one element.
# let rec l = 1 :: l ; ;
val l : int list =
[1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; ...]

Application of a recursive function to such a list risks looping until memory overflows.
Type declarations and pattern matching 53

# size l ; ;
Stack overflow during evaluation (looping recursion?).

Structural equality remains usable with such lists only when physical equality is first
verified:
# l=l ; ;
- : bool = true

In short, if you define a new list, even an equal one, you must not use the structural
equality test on pain of seeing your program loop indefinitely. So we don’t recommend
attempting to evaluate the following example:

let rec l2 = 1::l2 in l=l2 ;;

On the other hand, physical equality always remains possible.


# let rec l2 = 1 :: l2 in l==l2 ; ;
- : bool = false

The predicate == tests equality of an immediate value or sharing of a structured object


(equality of the address of the value). We will use it to verify that in traversing a list
we don’t retraverse a sublist which was already examined. First of all, we define the
function memq, which verifies the presence of an element in the list by relying on physical
equality. It is the counterpart to the function mem which tests structural equality; these
two functions belong to the module List.
# let rec memq a l = match l with
[] → false
| b :: l → (a==b) or (memq a l) ; ;
val memq : ’a -> ’a list -> bool = <fun>

The size computation function is redefined, storing the list of lists already examined
and halting if a list is encountered a second time.
# let special size l =
let rec size aux previous l = match l with
[] → 0
| _::l1 → if memq l previous then 0
else 1 + (size aux (l :: previous) l1)
in size aux [] l ; ;
val special_size : ’a list -> int = <fun>
# special size [1;2;3;4] ; ;
- : int = 4
# special size l ; ;
- : int = 1
# let rec l1 = 1 :: 2 :: l2 and l2 = 1 :: 2 :: l1 in special size l1 ; ;
- : int = 4
54 Chapter 2 : Functional programming

Typing, domain of definition, and


exceptions
The inferred type of a function corresponds to a subset of its domain of definition. Just
because a function takes a parameter of type int doesn’t mean it will know how to
compute a value for all integers passed as parameters. In general this problem is dealt
with using Objective Caml’s exception mechanism. Raising an exception results in a
computational interruption which can be intercepted and handled by the program. For
this to happen program execution must have registered an exception handler before
the computation of the expression which raises this exception.

Partial functions and exceptions


The domain of definition of a function corresponds to the set of values on which the
function carries out its computation. There are many mathematical functions which
are partial; we might mention division or taking the natural log. This problem also
arises for functions which manipulate more complex data structures. Indeed, what is
the result of computing the first element of an empty list? In the same way, evaluation
of the factorial function on a negative integer can lead to an infinite recursion.

Several exceptional situations may arise during execution of a program, for example
an attempt to divide by zero. Trying to divide a number by zero will provoke at best a
program halt, at worst an inconsistent machine state. The safety of a programming lan-
guage comes from the guarantee that such a situation will not arise for these particular
cases. Exceptions are a way of responding to them.

Division of 1 by 0 will cause a specific exception to be raised:


# 1/0; ;
Uncaught exception: Division_by_zero
The message Uncaught exception: Division_by_zero indicates on the one hand
that the Division by zero exception has been raised, and on the other hand that it
has not been handled. This exception is among the core declarations of the language.
Often, the type of a function does not correspond to its domain of definition when a
pattern-matching is not exhaustive, that is, when it does not match all the cases of a
given expression. To prevent such an error, Objective Caml prints a message in such a
case.
# let head l = match l with h :: t → h ; ;
Characters 14-36:
Warning: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
[]
val head : ’a list -> ’a = <fun>
Typing, domain of definition, and exceptions 55

If the programmer nevertheless keeps the incomplete definition, Objective Caml will
use the exception mechanism in the case of an erroneous call to the partial function:
# head [] ; ;
Uncaught exception: Match_failure("", 14, 36)

Finally, we have already met with another predefined exception: Failure. It takes an
argument of type string. One can raise this exception using the function failwith.
We can use it in this way to complete the definition of our head:
# let head = function
[] → failwith "Empty list"
| h :: t → h; ;
val head : ’a list -> ’a = <fun>
# head [] ; ;
Uncaught exception: Failure("Empty list")

Definition of an exception
In Objective Caml, exceptions belong to a predefined type exn. This type is very
special since it is an extensible sum type: the set of values of the type can be extended
by declaring new constructors9 . This detail lets users define their own exceptions by
adding new constructors to the type exn.
The syntax of an exception declaration is as follows:

Syntax : exception Name ;;


or

Syntax : exception Name of t ;;

Here are some examples of exception declarations:


# exception MY EXN; ;
exception MY_EXN
# MY EXN; ;
- : exn = MY_EXN
# exception Depth of int; ;
exception Depth of int
# Depth 4; ;
- : exn = Depth(4)
Thus an exception is a full-fledged language value.

9. Translator’s note: Thanks to the new “polymorphic variants” feature of Objective Caml 3.00, some
other sum types can now be extended as well
56 Chapter 2 : Functional programming

The names of exceptions are constructors. So they nec-


Warning
essarily begin with a capital letter.

# exception lowercase ; ;
Characters 11-20:
Syntax error

Exceptions are monomorphic: they do not have type


Warning parameters in the declaration of the type of their argu-
ment.

# exception Value of ’a ; ;
Characters 20-22:
Unbound type parameter ’a
A polymorphic exception would permit the definition of functions with an arbitrary
return type as we will see further on, page 58.

Raising an exception
The function raise is a primitive function of the language. It takes an exception as an
argument and has a completely polymorphic return type.
# raise ; ;
- : exn -> ’a = <fun>
# raise MY EXN; ;
Uncaught exception: MY_EXN
# 1+(raise MY EXN); ;
Uncaught exception: MY_EXN
# raise (Depth 4); ;
Uncaught exception: Depth(4)
It is not possible to write the function raise in Objective Caml. It must be predefined.

Exception handling
The whole point of raising exceptions lies in the ability to handle them and to direct
the sequence of computation according to the value of the exception raised. The order
of evaluation of an expression thus becomes important for determining which exception
is raised. We are leaving the purely functional context, and entering a domain where
the order of evaluation of arguments can change the result of a computation, as will
be discussed in the following chapter (see page 85).
The following syntactic construct, which computes the value of an expression, permits
the handling of an exception raised during this computation:
Typing, domain of definition, and exceptions 57

try expr with


| p1 –> expr1
Syntax : ..
.
| pn –> exprn

If the evaluation of expr does not raise any exception, then the result is that of the
evaluation of expr. Otherwise, the value of the exception which was raised is pattern-
matched; the value of the expression corresponding to the first matching pattern is
returned. If none of the patterns corresponds to the value of the exception then the
latter is propagated up to the next outer try-with entered during the execution of the
program. Thus pattern matching an exception is always considered to be exhaustive.
Implicitly, the last pattern is | e -> raise e. If no matching exception handler is
found in the program, the system itself takes charge of intercepting the exception and
terminates the program while printing an error message.
One must not confuse computing an exception (that is, a value of type exn) with raising
an exception which causes computation to be interrupted. An exception being a value
like others, it can be returned as the result of a function.
# let return x = Failure x ; ;
val return : string -> exn = <fun>
# return "test" ; ;
- : exn = Failure("test")
# let my raise x = raise (Failure x) ; ;
val my_raise : string -> ’a = <fun>
# my raise "test" ; ;
Uncaught exception: Failure("test")
We note that applying my raise does not return any value while applying return
returns one of type exn.

Computing with exceptions


Beyond their use for handling exceptional values, exceptions also support a specific
programming style and can be the source of optimizations. The following example
finds the product of all the elements of a list of integers. We use an exception to
interrupt traversal of the list and return the value 0 when we encounter it.
# exception Found zero ; ;
exception Found_zero
# let rec mult rec l = match l with
[] → 1
| 0 :: _ → raise Found zero
| n :: x → n * (mult rec x) ; ;
val mult_rec : int list -> int = <fun>
# let mult list l =
try mult rec l with Found zero → 0 ; ;
val mult_list : int list -> int = <fun>
# mult list [1;2;3;0;5;6] ; ;
58 Chapter 2 : Functional programming

- : int = 0
So all the computations standing by, namely the multiplications by n which follow each
of the recursive calls, are abandoned. After encountering raise, computation resumes
from the pattern-matching under with.

Polymorphism and return values of


functions
Objective Caml’s parametric polymorphism permits the definition of functions whose
return type is completely unspecified. For example:
# let id x = x ; ;
val id : ’a -> ’a = <fun>

However, the return type depends on the type of the argument. Thus, when the function
id is applied to an argument, the type inference mechanism knows how to instantiate
the type variable ’a. So for each particular use, the type of id can be determined.
If this were not so, it would no longer make sense to use strong static typing, entrusted
with ensuring execution safety. Indeed, a function of completely unspecified type such
as ’a -> ’b would allow any type conversion whatsoever, which would inevitably lead
to a run-time error since the physical representations of values of different types are
not the same.

Apparent contradiction
However, it is possible in the Objective Caml language to define a function whose return
type contains a type variable which does not appear in the types of its arguments. We
will consider several such examples and see why such a possibility is not contradictory
to strong static typing.
Here is a first example:
# let f x = [] ; ;
val f : ’a -> ’b list = <fun>

This function lets us construct a polymorphic value from anything at all:


# f () ; ;
- : ’_a list = []
# f "anything at all" ; ;
- : ’_a list = []

Nevertheless, the value obtained isn’t entirely unspecified: we’re dealing with a list. So
it can’t be used just anywhere.
Desktop Calculator 59

Here are three examples whose type is the dreaded ’a -> ’b:
# let rec f1 x = f1 x ; ;
val f1 : ’a -> ’b = <fun>
# let f2 x = failwith "anything at all" ; ;
val f2 : ’a -> ’b = <fun>
# let f3 x = List.hd [] ; ;
val f3 : ’a -> ’b = <fun>

These functions are not, in fact, dangerous vis-a-vis execution safety, since it isn’t
possible to use them to construct a value: the first one loops forever, the latter two
raise an exception which interrupts the computation.
Similarly, it is in order to prevent functions of type ’a -> ’b from being defined that
new exception constructors are forbidden from having arguments whose type contains
a variable.
Indeed, if one could declare a polymorphic exception Poly exn of type ’a -> exn, one
could then write the function:
let f = function
0 → raise (Poly exn false)
| n → n+1 ; ;

The function f being of type int -> int and Poly exn being of type ’a -> exn, one
could then define:
let g n = try f n with Poly exn x → x+1 ; ;
This function is equally well-typed (since the argument of Poly exn may be arbitrary)
and now, evaluation of (g 0) would end up in an attempt to add an integer and a
boolean!

Desktop Calculator
To understand how a program is built in Objective Caml, it is necessary to develop one.
The chosen example is a desktop calculator—that is, the simplest model, which only
works on whole numbers and only carries out the four standard arithmetic operations.
To begin, we define the type key to represent the keys of a pocket calculator. The latter
has fifteen keys, namely: one for each operation, one for each digit, and the = key.
# type key = Plus | Minus | Times | Div | Equals | Digit of int ; ;
We note that the numeric keys are gathered under a single constructor Digit taking
an integer argument. In fact, some values of type key don’t actually represent a key.
For example, (Digit 32) is a possible value of type key, but doesn’t represent any of
the calculator’s keys.
So we write a function valid which verifies that its argument corresponds to a calcu-
lator key. The type of this function is key -> bool, that is, it takes a value of type
key as argument and returns a value of type bool.
60 Chapter 2 : Functional programming

The first step is to define a function which verifies that an integer is included between
0 and 9. We declare this function under the name is digit:
# let is digit = function x → (x>=0) && (x<=9) ; ;
val is_digit : int -> bool = <fun>

We then define the function valid by pattern-matching over its argument of type key:

# let valid ky = match ky with


Digit n → is digit n
| _ → true ; ;
val valid : key -> bool = <fun>
The first pattern is applied when the argument of valid is a value made with the Digit
constructor; in this case, the argument of Digit is tested by the function is digit.
The second pattern is applied to every other kind of value of type key. Recall that
thanks to typing, the value being matched is necessarily of type key.
Before setting out to code the calculator mechanism, we will specify a model allowing
us to describe from a formal point of view the reaction to the activation of one of the
device’s keys. We will consider a pocket calculator to have four registers in which are
stored respectively the last computation done, the last key activated, the last operator
activated, and the number printed on the screen. The set of these four registers is
called the state of the calculator; it is modified by each keypress on the keypad. This
modification is called a transition and the theory governing this kind of mechanism is
that of automata. A state will be represented in our program by a record type:
# type state = {
lcd : int; (* last computation done *)
lka : key; (* last key activated *)
loa : key; (* last operator activated *)
vpr : int (* value printed *)
} ;;

Figure 2.6 gives an example of a sequence of transitions.

state key
(0, =, =, 0) 3
−→ (0, 3, =, 3) +
−→ (3, +, +, 3) 2
−→ (3, 2, +, 2) 1
−→ (3, 1, +, 21) ×
−→ (24, ∗, ∗, 24) 2
−→ (24, 2, ∗, 2) =
−→ (48, =, =, 48)

Figure 2.6: Transitions for 3 + 21 ∗ 2 = .


Desktop Calculator 61

In what follows we need the function evaluate which takes two integers and a value
of type key containing an operator and which returns the result of the operation
corresponding to the key, applied to the integers. This function is defined by pattern-
matching over its last argument, of type key:
# let evaluate x y ky = match ky with
Plus → x + y
| Minus → x - y
| Times → x * y
| Div → x / y
| Equals → y
| Digit _ → failwith "evaluate : no op"; ;
val evaluate : int -> int -> key -> int = <fun>

Now we give the definition of the transition function by enumerating all possible cases.
We assume that the current state is the quadruplet (a, b, ⊕, d):
• a key with digit x is pressed, then there are two cases to consider:
– the last key pressed was also a digit. So it is a number which the user of the
pocket calculator is in the midst of entering; consequently the digit x must
be affixed to the printed value, i.e., replacing it with d × 10 + x. The new
state is:
(a, (Digit x), ⊕, d × 10 + x)
– the last key pressed was not a digit. So it is the start of a new number which
is being entered. The new state is:

(a, (Digit x), ⊕, x)

• a key with operator ⊗ has been pressed, the second operand of the operation has
thus been completely entered and the calculator has to deal with carrying out
this operation. It is to this end that the last operation (here ⊕) is stored. The
new state is:
(⊕d, ⊗, ⊗, a ⊕ d)

To write the function transition, it suffices to translate the preceding definition word
for word into Objective Caml: the definition by cases becomes a definition by pattern-
matching over the key passed as an argument. The case of a key, which itself is made up
of two cases, is handled by the local function digit transition by pattern-matching
over the last key activated.
# let transition st ky =
let digit transition n = function
Digit _ → { st with lka=ky; vpr=st.vpr*10+n }
| _ → { st with lka=ky; vpr=n }
in
match ky with
Digit p → digit transition p st.lka
| _ → let res = evaluate st.lcd st.vpr st.loa
in { lcd=res; lka=ky; loa=ky; vpr=res } ; ;
62 Chapter 2 : Functional programming

val transition : state -> key -> state = <fun>


This function takes a state and a key and computes the new state.
We can now test this program on the previous example:
# let initial state = { lcd=0; lka=Equals; loa=Equals; vpr=0 } ; ;
val initial_state : state = {lcd=0; lka=Equals; loa=Equals; vpr=0}
# let state2 = transition initial state (Digit 3) ; ;
val state2 : state = {lcd=0; lka=Digit 3; loa=Equals; vpr=3}
# let state3 = transition state2 Plus ; ;
val state3 : state = {lcd=3; lka=Plus; loa=Plus; vpr=3}
# let state4 = transition state3 (Digit 2) ; ;
val state4 : state = {lcd=3; lka=Digit 2; loa=Plus; vpr=2}
# let state5 = transition state4 (Digit 1) ; ;
val state5 : state = {lcd=3; lka=Digit 1; loa=Plus; vpr=21}
# let state6 = transition state5 Times ; ;
val state6 : state = {lcd=24; lka=Times; loa=Times; vpr=24}
# let state7 = transition state6 (Digit 2) ; ;
val state7 : state = {lcd=24; lka=Digit 2; loa=Times; vpr=2}
# let state8 = transition state7 Equals ; ;
val state8 : state = {lcd=48; lka=Equals; loa=Equals; vpr=48}

This run can be written in a more concise way using a function applying a sequence of
transitions corresponding to a list of keys passed as an argument.

# let transition list st ls = List.fold left transition st ls ; ;


val transition_list : state -> key list -> state = <fun>
# let example = [ Digit 3; Plus; Digit 2; Digit 1; Times; Digit 2; Equals ]
in transition list initial state example ; ;
- : state = {lcd=48; lka=Equals; loa=Equals; vpr=48}

Exercises

Merging two lists


1. Write a function merge i which takes as input two integer lists sorted in in-
creasing order and returns a new sorted list containing the elements of the first
two.
2. Write a general function merge which takes as argument a comparison function
and two lists sorted in this order and returns the list merged in the same order.
The comparison function will be of type ’a → ’a → bool.
3. Apply this function to two integer lists sorted in decreasing order, then to two
string lists sorted in decreasing order.
4. What happens if one of the lists is not in the required decreasing order?
Exercises 63

5. Write a new list type in the form of a record containing three fields: the
conventional list, an order function and a boolean indicating whether the list is
in that order.
6. Write the function insert which adds an element to a list of this type.
7. Write a function sort which insertion sorts the elements of a list.
8. Write a new function merge for these lists.

Lexical trees
Lexical trees (or tries) are used for the representation of dictionaries.
# type lex node = Letter of char * bool * lex tree
and lex tree = lex node list; ;
# type word = string; ;
The boolean value in lex node marks the end of a word when it equals true. In such
a structure, the sequence of words “fa, false, far, fare, fried, frieze” is stored in the
following way:

F
A* R
L R* I


S E* E


E* D* Z
 

E*


An asterisk (*) marks the end of a word.

1. Write the function exists which tests whether a word belongs to a dictionary
of type lex tree.
2. Write a function insert which takes a word and a dictionary and returns a new
dictionary which additionally contains this word. If the word is already in the
dictionary, it is not necessary to insert it.
3. Write a function construct which takes a list of words and constructs the
corresponding dictionary.
4. Write a function verify which takes a list of words and a dictionary and returns
the list of words not belonging to this dictionary.
5. Write a function select which takes a dictionary and a length and returns the
set of words of this length.
64 Chapter 2 : Functional programming

Graph traversal
We define a type ’a graph representing directed graphs by adjacency lists containing
for each vertex the list of its successors:
# type ’a graph = ( ’a * ’a list) list ; ;

1. Write a function insert vtx which inserts a vertex into a graph and returns the
new graph.
2. Write a function insert edge which adds an edge to a graph already possessing
these two vertices.
3. Write a function has edges to which returns all the vertices following directly
from a given vertex.
4. Write a function has edges from which returns the list of all the vertices leading
directly to a given vertex.

Summary
This chapter has demonstrated the main features of functional programming and para-
metric polymorphism, which are two essential features of the Objective Caml language.
The syntax of the expressions in the functional core of the language as well as those of
the types which have been described allowed us to develop our first programs. More-
over, the profound difference between the type of a function and its domain of defini-
tion was underlined. Introducing the exception mechanism allowed us to resolve this
problem and already introduces a new programming style in which one specifies how
computations should unfold.

To learn more
The computation model for functional languages is λ-calculus, which was invented by
Alonzo Church in 1932. Church’s goal was to define a notion of effective computability
through the medium of λ-definability. Later, it became apparent that the notion thus
introduced was equivalent to the notions of computability in the sense of Turing (Tur-
ing machine) and Gödel-Herbrand (recursive functions). This coı̈ncidence leads one to
think that there exists a universal notion of computability, independent of particular
formalisms: this is Church’s thesis. In this calculus, the only two constructions are ab-
straction and application. Data structures (integers, booleans, pairs, ...) can be coded
by λ-termes.
Functional languages, of which the first representative was Lisp, implement this model
and extend it mainly with more efficient data structures. For the sake of efficiency, the
first functional languages implemented physical modifications of memory, which among
other things forced the evaluation strategy to be immediate, or strict, evaluation. In
this strategy, the arguments of functions are evaluated before being passed to the
To learn more 65

function. It is in fact later, for other languages such as Miranda, Haskell, or LML, that
the strategy of delayed (lazy, or call-by-need) evaluation was implemented for pure
functional languages.
Static typing, with type inference, was promoted by the ML family at the start of the
80’s. The web page

Link: http://www.pps.jussieu.fr/˜cousinea/Caml/caml history.html

presents a historical overview of the ML language. Its computation model is typed


λ-calculus, a subset of λ-calculus. It guarantees that no type error will occur during
program execution. Nevertheless “completely correct” programs can be rejected by
ML’s type system. These cases seldom arise and these programs can always be rewritten
in such a way as to conform to the type system.
The two most-used functional languages are Lisp and ML, representatives of impure
functional languages. To deepen the functional approach to programming, the books
[ASS96] and [CM98] each present a general programming course using the languages
Scheme (a dialect of Lisp) and Caml-Light, respectively.
76 Chapter 3 : Imperative Programming

Likewise, when you apply a polymorphic value to a polymorphic function, you get a
weak type variable, because you must not exclude the possibility that the function may
construct physically modifiable values. In other words, the result of the application is
always monomorphic.
# (function x → x) [] ;;
- : ’_a list = []

You get the same result with partial application:


# let f a b = a ; ;
val f : ’a -> ’b -> ’a = <fun>
# let g = f 1 ; ;
val g : ’_a -> int = <fun>

To get a polymorphic type back, you have to abstract the second argument of f and
then apply it:
# let h x = f 1 x ; ;
val h : ’a -> int = <fun>

In effect, the expression which defines h is the functional expression function x →


f 1 x. Its evaluation produces a closure which does not risk producing a side effect,
because the body of the function is not evaluated.

In general, we distinguish so-called “non-expansive” expressions, whose calculation we


are sure carries no risk of causing a side effect, from other expressions, called “expan-
sive.” Objective Caml’s type system classifies expressions of the language according to
their syntactic form:
• “non-expansive” expressions include primarily variables, constructors of non-
mutable values, and abstractions;
• “expansive” expressions include primarily applications and constructors of mod-
ifiable values. We can also include here control structures like conditionals and
pattern matching.

Input-Output
Input-output functions do calculate a value (often of type unit) but during their
calculation they cause a modification of the state of the input-output peripherals:
modification of the state of the keyboard buffer, outputting to the screen, writing
in a file, or modification of a read pointer. The following two types are predefined:
in channel and out channel for, respectively, input channels and output channels.
When an end of file is met, the exception End of file is raised. Finally, the following
three constants correspond to the standard channels for input, output, and error in
Unix fashion: stdin, stdout, and stderr.
Input-Output 77

Channels
The input-output functions from the Objective Caml standard library manipulate com-
munication channels: values of type in channel or out channel. Apart from the three
standard predefined values, the creation of a channel uses one of the following func-
tions:
# open in; ;
- : string -> in_channel = <fun>
# open out; ;
- : string -> out_channel = <fun>
open in opens the file if it exists2 , and otherwise raises the exception Sys error.
open out creates the specified file if it does not exist or truncates it if it does.
# let ic = open in "koala"; ;
val ic : in_channel = <abstr>
# let oc = open out "koala"; ;
val oc : out_channel = <abstr>
The functions for closing channels are:
# close in ; ;
- : in_channel -> unit = <fun>
# close out ; ;
- : out_channel -> unit = <fun>

Reading and Writing


The most general functions for reading and writing are the following:
# input line ; ;
- : in_channel -> string = <fun>
# input ; ;
- : in_channel -> string -> int -> int -> int = <fun>
# output ; ;
- : out_channel -> string -> int -> int -> unit = <fun>

• input line ic: reads from input channel ic all the characters up to the first
carriage return or end of file, and returns them in the form of a list of characters
(excluding the carriage return).
• input ic s p l: attempts to read l characters from an input channel ic and
stores them in the list s starting from the pth character. The number of characters
actually read is returned.
• output oc s p l: writes on an output channel oc part of the list s, starting at
the p-th character, with length l.

2. With appropriate read permissions, that is.


78 Chapter 3 : Imperative Programming

The following functions read from standard input or write to standard output:
# read line ; ;
- : unit -> string = <fun>
# print string ; ;
- : string -> unit = <fun>
# print newline ; ;
- : unit -> unit = <fun>

Other values of simple types can also be read directly or appended. These are the
values of types which can be converted into lists of characters.

Local declarations and order of evaluation We can simulate a sequence of print-


outs with expressions of the form let x = e1 in e2 . Knowing that, in general, x is
a local variable which can be used in e2 , we know that e1 is evaluated first and then
comes the turn of e2 . If the two expressions are imperative functions whose results
are () but which have side effects, then we have executed them in the right order. In
particular, since we know the return value of e1 —the constant () of type unit—we get
a sequence of printouts by writing the sequence of nested declarations which pattern
match on () .

# let () = print string "and one," in


let () = print string " and two," in
let () = print string " and three" in
print string " zero"; ;
and one, and two, and three zero- : unit = ()

Example: Higher/Lower
The following example concerns the game “Higher/Lower” which consists of choosing
a number which the user must guess at. The program indicates at each turn whether
the chosen number is smaller or bigger than the proposed number.

# let rec hilo n =


let () = print string "type a number: " in
let i = read int ()
in
if i = n then
let () = print string "BRAVO" in
let () = print newline ()
in print newline ()
else
let () =
if i < n then
Control Structures 79

let () = print string "Higher"


in print newline ()
else
let () = print string "Lower"
in print newline ()
in hilo n ; ;
val hilo : int -> unit = <fun>

Here is an example session:

# hilo 64;;
type a number: 88
Lower
type a number: 44
Higher
type a number: 64
BRAVO

- : unit = ()

Control Structures
Input-output and modifiable values produce side-effects. Their use is made easier by
an imperative programming style furnished with new control structures. We present in
this section the sequence and iteration structures.

We have already met the conditional control structure on page 18, whose abbreviated
form if then patterns itself on the imperative world. We will write, for example:
# let n = ref 1 ; ;
val n : int ref = {contents=1}
# if !n > 0 then n := !n - 1 ; ;
- : unit = ()

Sequence
The first of the typically imperative structures is the sequence. This permits the left-
to-right evaluation of a sequence of expressions separated by semicolons.
Syntax : expr1 ; . . . ; exprn

A sequence of expressions is itself an expression, whose value is that of the last expres-
sion in the sequence (here, exprn ). Nevertheless, all the expressions are evaluated, and
in particular their side-effects are taken into account.
# print string "2 = "; 1+1 ; ;
Bibliography

[AC96] Marı́a-Virginia Aponte and Giuseppe Castagna. Programmation modulaire


avec surcharge et liaison tardive. In Journées Francophones des Langages
Applicatifs. INRIA, January 1996.
[AHU83] Alfred Aho, John Hopcroft, and Jeffrey Ullman. Data Structures and Al-
gorithms. Addison-Wesley, 1983.
[And91] G. Andrews. Concurrent Programming : Principles and practices. Ben-
jamin Cumming, 1991.
[Ari90] Ben Ari. Principles of Concurrent and Distributed Programming. Prentice
Hall, second edition, 1990.
[ASS96] Harold Abelson, Gerald Jay Sussman, and Julie Sussman. Structure and
Interpretation of Computer Programs. MIT Press, second edition, 1996.
[ASU86] Alfred V. Aho, Ravi Sethi, and Jeffrey D. Ullman. Compilers: principles,
techniques, and tools. Addison-Wesley, 1986.
[BLH00] Olivier Ballereau, Frédéric Loulergue, and Gaétan Hains. High level BSP
programming: BSML and BSlambda. In Stephen Gilmore, editor, Trends
in Functional Programming, volume 2. Intellect, 2000.
[CC92] Emmanuel Chailloux and Guy Cousineau. Programming images in ML. In
Proceedings of the ACM SIGPLAN Workshop on ML and its Applications,
1992.
[CCM87] Guy Cousineau, Pierre-Louis Curien, and Michel Mauny. The Categorical
Abstract Machine. Science of Computer Programming, 8:173–202, 1987.
[CDM98] Rémy Card, Éric Dumas, and Franck Mével. The Linux Kernel Book.
Wiley, John & Sons, 1998.
716 Bibliography

[CKL96] Emmanuel Chailloux, Laurent Kirsch, and Stéphane Lucas. Caml2sml, un


outil d’aide à la traduction de Caml vers Sml. In Journées Francophones
des Langages Applicatifs. INRIA, January 1996.
[CL99] Sylvain Conchon and Fabrice Le Fessant. JoCaml: mobile agents for
Objective-Caml. In International Symposium on Agent Systems and Ap-
plications, 1999.
[CM98] Guy Cousineau and Michel Mauny. The functional approach to program-
ming. Cambridge University Press, 1998.
[CP95] Paul Caspi and Marc Pouzet. A functional extension to LUSTRE. In
8th International Symposium on Languages for Intensional Programming,
Sydney, May 1995. World Scientific.
[CS94] Emmanuel Chailloux and Ascánder Suárez. mlPicTeX, a picture environ-
ment for LaTeX. In Proceedings of the ACM SIGPLAN Workshop on ML
and its Applications, 1994.
[DDLP98] Marco Danelutto, Roberto Di Cosmo, Xavier Leroy, and Susanna Pelagatti.
Parallel functional programming with skeletons: the ocamlp3l experiment.
In ML Workshop. ACM SIGPLAN, 1998.
[DEMN98] Roland Ducournau, Jérôme Euzenat, Gérald Masini, and Amedeo Napoli,
editors. Langages et modèles à objets: état et perspectives de la recherche.
INRIA, 1998.

[Eng98] Emmanuel Engel. Extensions sûres et praticables du système de types de


ML en présence d’un langage de modules et de traits impératifs. PhD thesis,
Université Paris-Sud, Orsay, France, mai 1998.
[FC95] Christian Foisy and Emmanuel Chailloux. Caml Flight: a Portable SPMD
Extension of ML for Distributed Memory Multiprocessors. In Conference
on High Performance Functional Computing, April 1995.
[FF98] Robert B. Findler and Matthew Flatt. Modular Object-Oriented Program-
ming with Units and Mixins. In International Conference on Functional
Programming. ACM, 1998.
[FW00] Jun Furuse and Pierre Weis. Entrées/Sorties de valeurs en Caml. In
JFLA’2000 : Journées Francophones des Langages Applicatifs, Mont Saint-
Michel, January 2000. INRIA.
[GHJV95] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design
Patterns. Addison-Wesley, 1995.
[HF+ 96] Pieter Hartel, Marc Feeley, et al. Benchmarking implementations of func-
tional languages with “Pseudoknot”, a float-intensive benchmark. Journal
of Functional Programming, 6(4), 1996.
[HS94] Samuel P. Harbison and Guy L. Steele. C: A reference manual. Prentice-
Hall, fourth edition, 1994.
Bibliography 717

[Hui97] Christian Huitema. IPv6 – The New Internet Protocol. Prentice Hall, 1997.
[Jon98] Richard Jones. Garbage Collection: Algorithms for Automatic Dynamic
Memory Management. John Wiley & Sons, 1998.
[Ler90] Xavier Leroy. The ZINC experiment: an economical implementation of the
ML language. Technical report 117, INRIA, 1990.
[Ler92] Xavier Leroy. Programmation du système Unix en Caml Light. Technical
report 147, INRIA, 1992.
[LMB92] John R. Levine, Tony Mason, and Doug Brown. Lex & Yacc. O’Reilly,
second edition, 1992.
[LRVD99] Xavier Leroy, Didier Rémy, Jérôme Vouillon, and Damien Doligez. The
objective caml system release 2.04. Technical report, INRIA, December
1999.
[MdR92] Michel Mauny and Daniel de Rauglaudre. Parser in ML. Research report
1659, INRIA, avril 1992.
[MNC+ 91] Gérald Masini, Amedeo Napoli, Dominique Colnet, Daniel Léonard, and
Karl Tombre. Object-Oriented Languages. Academic Press, New York,
1991.

[MT91] Robin Milner and Mads Tofte. Commentary on Standard ML. MIT Press,
1991.

[MTH97] Robin Milner, Mads Tofte, and Robert Harper. The Definition of Standard
ML (revised). MIT Press, 1997.

[Rep99] John Reppy. Concurrent Programming in ML. Cambridge University Press,


1999.

[Rob89] Eric S. Robert. Implementing exceptions in C. Technical Report SRC-40,


Digital Equipment, 1989.

[Rou96] François Rouaix. A Web navigator with applets in Caml. In Proceedings


of the 5th International World Wide Web Conference, in Computer Net-
works and Telecommunications Networking, volume 28, pages 1365–1371.
Elsevier, May 1996.
[RV98] Didier Rémy and Jérôme Vouillon. Objective ML: An effective object-
oriented extension to ML. Theory And Practice of Object Systems, 4(1):27–
50, 1998. A preliminary version appeared in the proceedings of the 24th
ACM Conference on Principles of Programming Languages, 1997.
[Sed88] Robert Sedgewick. Algorithms. Addison-Wesley, second edition, 1988.
[Ste92] W. Richard Stevens. Advanced Programming in the UNIX Environment.
Addison-Wesley, 1992.
718 Bibliography

[Tho99] Simon Thompson. Haskell: The Craft of Functional Programming. Addison


Wesley, seconde edition, 1999.
[Tur85] David A. Turner. Miranda: A non-strict functional language with polymor-
phic types. In J. Jouannaud, editor, Proceedings International Conference
on Functional Programming Languages and Computer Architecture, vol-
ume 201 of Lecture Notes in Computer Science, pages 1–16, New York,
NY, September 1985. Springer-Verlag.
[Wil92] Paul. R. Wilson. Uniprocessor garbage collection techniques. In Interna-
tional Workshop on Memory Management, number 637 in LNCS, pages
1–42. Springer-Verlag, 1992.
[Wri95] Andrew K. Wright. Simple imperative polymorphism. Lisp and Symbolic
Computation, 8(4):343–356, 1995.
Index of concepts
—A— bytecode . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
dynamic loading . . . . . . . . . . . . . . . 241
abstract the compiler . . . . . . . . . . see compiler
class . . . . . . . . . . . . . . . . . . . . . . . . . . . 450 bytecode . . . . . . . . . . . . . . . . . . . see bytecode
method . . . . . . . . . . . . . . . . . . . . . . . . 450
abstract machine . . . . . . . . . . . . . . . . . . . 199
abstract type . . . . . . . . . . . . . . . . . . . . . . . 407
—C—
abstraction . . . . . . . . . . . . . . . . . . . . . . . . . . 21 C (the langage) . . . . . . . . . . . . . . . . . . . . . 315
affectation . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 callback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
aggregation . . . . . . . . . . . . . . . . . . . . . . . . . 441 cartesian product . . . . . . . . . . . . . . . . . . . . 17
allocation character . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
dynamic . . . . . . . . . . . . . . . . . . . . . . . 248 character string . . . . . . . . . . . . . . . . . . . . . . 15
static . . . . . . . . . . . . . . . . . . . . . . . . . . 248 character strings . . . . . . . . . . . . . . . . . . . . . 72
application . . . . . . . . . . . . . . . . . . . . . . . . . . 21 class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436
of a function . . . . . . . . . . . . . . . . . . . . 21 abstract . . . . . . . . . . . . . . . . . . . . . . . 450
partial . . . . . . . . . . . . . . . . . . . . . . . . . . 25 inheritance . . . . . . . . . . . . . . . . . . . . . 443
arity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23instance . . . . . . . . . . . . . . . . . . . . . . . 440
array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 interface . . . . . . . . . . . . . . . . . . . . . . . 473
local declaration . . . . . . . . . . . . . . . 474
—B— multiple inheritance . . . . . . . . . . . . 457
open type . . . . . . . . . . . . . . . . . . . . . . 453
big numbers . . . . . . . . . . . . . . . . . . . . . . . . 239 parameterized . . . . . . . . . . . . . . . . . 460
binding type . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
delayed . . . . . . . . . . . . . . . . . . . . . . . . 446 variable . . . . . . . . . . . . . . . . . . . . . . . . 475
static . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 virtual . . . . . . . . . . . . . . . . . . . . . . . . . 450
BNF . . . . . . . . . . . . . . . . . . . . . . see grammar class instance . . . . . . . . . . . . . . . . . . . . . . . 440
boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 client-server . . . . . . . . . . . . . . . . . . . . . . . . 630
boucle d’interaction . . . . . . . . . . . . . . . . 205 closure . . . . . . . . . . . . . . . . . . . . . . . . . . . 23, 26
construction . . . . . . . . . . . . . . . . . . . 206 from C . . . . . . . . . . . . . . . . . . . . . . . . 343
options . . . . . . . . . . . . . . . . . . . . . . . . 205 representation . . . . . . . . . . . . . . . . . 332
720 Index of concepts

command line . . . . . . . . . . . . . . . . . . . . . . 234 destructor . . . . . . . . . . . . . . . . . . . . . . . . . . 250


parsing of . . . . . . . . . . . . . . . . . . . . . . 236 digest . . . . . . . . . . . . . . . . . . . . see fingerprint
communication channel . . . . . . . . . 77, 589 dot notation . . . . . . . . . . . . . . . . . . . . . . . . 214
communication pipes . . . . . . . . . . . . . . . 587 dynamic loading . . . . . . . . . . . . . . . . . . . . 241
named . . . . . . . . . . . . . . . . . . . . . . . . . 588
compilateur . . . . . . . . . . . . . . . . . . . . . . . . 197
compilation . . . . . . . . . . . . . . . . . . . . . . . . 197
—E—
portabilité . . . . . . . . . . . . . . . . . . . . . 208 environment . . . . . . . . . . . . . . . . . . . . 23, 332
unité . . . . . . . . . . . . . . . . . . . . . . . . . . 201 evaluation
compilation unit . . . . . . . . . . . . . . . . . . . . 201 deferred . . . . . . . . . . . . . . . . . . . . . . . 107
compiler évaluation
debug . . . . . . . . . . . . . . . . . . . . . . . . . . 278 retardée . . . . . . . . . . . . . . . . . . . . . . . 107
bytecode . . . . . . . . . . . . . . . . . . 199, 202 evaluation
command . . . . . . . . . . . . . . . . . . . . . . 201 order of evaluation . . . . . . . . . . . . . . 85
linking . . . . . . . . . . . . . . . . . . . . . . . . . 202 événement . . . . . . . . . . . . . . . . . . . . . . . . . . 132
native . . . . . . . . . . . . . . . . . . . . . . . . . 204 exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
profiling . . . . . . . . . . . . . . . . . . . . . . . 281 declaration . . . . . . . . . . . . . . . . . . . . . . 55
concurrency . . . . . . . . . . . . . . . . . . . 599, 600 handling . . . . . . . . . . . . . . . . . . . . . . . . 56
conditional . . . . . . . . . . . . . . . . . . . . . . . . . . 18 printing . . . . . . . . . . . . . . . . . . . . . . . . 238
conflict . . . . . . . . . . . . . . . . . . . . . see parsing raising . . . . . . . . . . . . . . . . . . . . . . . . . . 56
conservative . . . . . . . . . . . . . . . . . . . . . . . . 260 with C . . . . . . . . . . . . . . . . . . . . . . . . . 344
constraint . . . . . . . . . . . . . . . . . . . . . . . . . . 417 execution stack . . . . . . . . . . . . . . . . . . . . . 280
constructor . . . . . . . . . . . . . . . . . . . . . . 34, 45 expression
constant . . . . . . . . . . . . . . . . . . . . . . . . 45 functional . . . . . . . . . . . . . . . . . . . . . . . 21
functional . . . . . . . . . . . . . . . . . . . . . . . 46 rational . . . . . . . . . . . . . . . . . . . . . . . . 290
critical section . . . . . . . . . . . . . . . . . . . . . . 604 regular . . . . . . . . . . . . . . . . . . . . . . . . . 290
cyclic external declaration . . . . . see declaration
type . . . . . . . . . . . . . . . . . . . . . . . . . . . 699
—F—
—D— famine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 606
debugger . . . . . . . . . . . . . . . . . see debugging file
debugging . . . . . . . . . . . . . . . . . . . . . 273, 278 extension
declaration .ml . . . . . . . . . . . . . . . . . . . . . . . . . . 202
of an exception . . . . . . . . . . . . . . . . . 55 .mli . . . . . . . . . . . . . . . . . . . . . . . . . 202
external . . . . . . . . . . . . . . . . . . . . . . . 318 .mll . . . . . . . . . . . . . . . . . . . . . . . . . 293
of function . . . . . . . . . . . . . . . . . . . . . . 21 .mly . . . . . . . . . . . . . . . . . . . . . . . . . 303
global . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 interface . . . . . . . . . . . . . . . . . . . . . . . 202
local . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 finalization . . . . . . . . . . . . . . . . . . . . . . . . . 339
by matching . . . . . . . . . . . . . . . . . . . . 40 fingerprint . . . . . . . . . . . . . . . . . . . . . . . . . . 227
of an operator . . . . . . . . . . . . . . . . . . 25 floating-point number . . . . . . . . . . . . . . . . 13
recursive . . . . . . . . . . . . . . . . . . . . . . . . 27 floats
simultaneous global . . . . . . . . . . . . . 20 arrays of . . . . . . . . . . . . . . . . . . . . . . . 331
simultaneous local . . . . . . . . . . . . . . 21 representation . . . . . . . . . . . . . . . . . 331
of type . . . . . . . . . . . . . . . . . . . . . . . . . . 41 function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
scope . . . . . . . . . . . . . . . . . . . . . . . . . 49 for finalization . . . . . . . . . . . . . . . . . 339
of value . . . . . . . . . . . . . . . . . . . . . . . . . 19 higher order . . . . . . . . . . . . . . . . . . . . . 26
mutually recursive . . . . . . . . . . . . . . 28
Index of concepts 721

partial . . . . . . . . . . . . . . . . . . . . . . . . . . 54 installingObjective Caml


polymorphic . . . . . . . . . . . . . . . . . . . . 28 MacOS . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
trace . . . . . . . . . . . . . . . . . . . . . . . . 276 instance
recursive . . . . . . . . . . . . . . . . . . . . . . . . 27 class . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
trace . . . . . . . . . . . . . . . . . . . . . . . . 274 classe . . . . . . . . . . . . . . . . . . . . . . . . . . 436
registration with C . . . . . . . . . . . . . 343 variable . . . . . . . . . . . . . . . . . . . . . . . . 436
tail recursive . . . . . . . . . . . . . . . . . . . . 96 integer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
function call . . . . . . . . . . . . . see application interface . . . . . . . . . . . . . . . . . . . . . . . 407, 473
functional . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 graphical . . . . . . . . . . . . . . . . . . . . . . 351
functor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418 with C . . . . . . . . . . . . . . . . . . . . 317, 323
with the system . . . . . . . . . . . . . . . . 234
—G— interoperability . . . . . . . . . . . . . . . . . . . . . 315
intput-output . . . . . . . . . . . . . . . . . . . . . . 229
garbage collection . . . . . . . . . . see GC, 252 Is-a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443
garbage collector . . . . . . . . . . . . . . . . see GC
GC . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247,
, conservative . . . . . . . . . . . . . . . . . .
252
260
—L—
, generational . . . . . . . . . . . . . . . . . . 259 label . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 704
from C . . . . . . . . . . . . . . . . . . . . . . . . 335 lazy (data) . . . . . . . . . . . . . . . . . . . . . . . . . 107
incremental . . . . . . . . . . . . . . . . . . . . 260 lexical analysis . . . . . . . . . . . . . . . . . . . . . 288
major . . . . . . . . . . . . . . . . . . . . . . . . . . 261 ocamllex . . . . . . . . . . . . . . . . . . . . . . 293
minor . . . . . . . . . . . . . . . . . . . . . . . . . . 261 stream . . . . . . . . . . . . . . . . . . . . . . . . . 289
Stop&Copy . . . . . . . . . . . . . . . . . . . . 256 lexical unit . . . . . . . . . . . . . . . . . . . . . . . . . 295
grammar . . . . . . . . . . . . . . . . . . . . . . . . . . . 295 ocamlyacc . . . . . . . . . . . . . . . . . . . . . 304
contextual . . . . . . . . . . . . . . . . . . . . . 305 library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
definition . . . . . . . . . . . . . . . . . . . . . . 295 preloaded . . . . . . . . . . . . . . . . . . . . . . 215
rule . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295 standard . . . . . . . . . . . . . . . . . . . . . . . 215
linearization . . . . . . . . . . . . . . . . . . . . . . . . 228
—H— linking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
with C . . . . . . . . . . . . . . . . . . . . . . . . . 320
Has-a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441 list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
hashing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 association . . . . . . . . . . . . . . . . . . . . . 221
heap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 matching . . . . . . . . . . . . . . . . . . . . . . . 40

—I— —M—
identifier . . . . . . . . . . . . . . . . . . . . . . . . . . . 288 mémoire
inclusion récupération
polymorphism . . . . . . . . . . . . . . . . . 465 explicite . . . . . . . . . . . . . . . . . . . . . 250
inheritance . . . . . . . . . . . . . . . . . . . . . . . . . 443 implicite . . . . . . . . . . . . . . . . . . . . . 251
inlining . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 Mark&Sweep . . . . . . . . . . . . . . . . . . . . . . . 254
input-output . . . . . . . . . . . . . . . . . . . . . . . 223 matching . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
with C . . . . . . . . . . . . . . . . . . . . . . . . . 323 exhaustive . . . . . . . . . . . . . . . . . . . . . . 35
installing Objective Caml . . . . . . . . . . . . . 2 destructive . . . . . . . . . . . . . . . . . . . . . 111
Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 memory
online HTML help . . . . . . . . . . . . . . . 5 allocation . . . . . . . . . . . . . . . . . . . . . . 248
Unix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 automatic
Windows . . . . . . . . . . . . . . . . . . . . . . . . . 2 deallocation . . . . . . . . . . . . . . . . . 247
722 Index of concepts

cache . . . . . . . . . . . . . . . . . . . . . . . . . . 265 naming . . . . . . . . . . . . . . . . . . . . . . . . . 38


deallocation . . . . . . . . . . . . . . . 248, 249 wildcard . . . . . . . . . . . . . . . . . . . . . 34, 35
dynamic . . . . . . . . . . . . . . . . . . . . . . . 248 pattern matching . . . . . . . . . see matching
explicit deallocation . . . . . . . . . . . . 249 persistence . . . . . . . . . . . . . . . . . . . . . . . . . 228
management . . . . . . . . . . . . . . . . . . . 247 persistent
reclamation . . . . . . . . . . . . . . . . . . . . 265 value . . . . . . . . . . . . . . . . . . . . . . . . . . 228
static . . . . . . . . . . . . . . . . . . . . . . . . . . 248 pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
message sending . . . . . . . . . . . . . . . . . . . . 436 weak . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436 polymorphism . . . . . . . . . . . . . . . . . . . . . . . 28
abstract . . . . . . . . . . . . . . . . . . . . . . . 450 inclusion . . . . . . . . . . . . . . . . . . . . . . . 465
virtual . . . . . . . . . . . . . . . . . . . . . . . . . 450 portabilité . . . . . . . . . . . . . . . . . . . . . . . . . . 208
modifiable . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579
module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410 processus
constraint . . . . . . . . . . . . . . . . . . . . . . 411 création . . . . . . . . . . . . . . . . . . . 581, 602
dependency . . . . . . . . . . . . . . . . . . . . 272 léger . . . . . . . . . . . . . . . . . . . . . . . . . . . 600
local definition . . . . . . . . . . . . . . . . . 422 producteur-consommateur . . . . . . . . . . 607
opening . . . . . . . . . . . . . . . . . . . . . . . . 214 production rule . . . . . . . . . . . see grammar
parameterized . . . . . . . . . . . . . . . . . 418 profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
sub-module . . . . . . . . . . . . . . . . . . . . 417 bytecode . . . . . . . . . . . . . . . . . . 282, 283
mutual exclusion . . . . . . . . . . . . . . . . . . . 604 natif . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
native . . . . . . . . . . . . . . . . . . . . . . . . . 284
—O— protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . 643
http . . . . . . . . . . . . . . . . . . . . . . . . . . . 644
object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436
copy . . . . . . . . . . . . . . . . . . . . . . . . . . . 470
creation . . . . . . . . . . . . . . . . . . . . . . . . 440 —R—
OCamlBrowser . . . . . . . . . . . . . . . . . . . . . 712 reader-writer . . . . . . . . . . . . . . . . . . . . . . . 610
operator record . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
associativity . . . . . . . . . . . . . . . . . . . 305 mutable field . . . . . . . . . . . . . . . . . . . . 73
declaration . . . . . . . . . . . . . . . . . . . . . . 25 reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
precedence . . . . . . . . . . . . . . . . . . . . . 305 root . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
optional (argument) . . . . . . . . . . . . . . . . 706
—S—
—P— scope of a variable . . . . . . . . . . . . . . . . . . . 26
pair . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 self . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445
parsing semaphore . . . . . . . . . . . . . . . . . . . . . . . . . . 608
bottom-up . . . . . . . . . . . . . . . . . . . . . 299 Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
conflict . . . . . . . . . . . . . . . . . . . . 300, 305 session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
shift-reduce . . . . . . . . . . . . . . . . . . 301 sharing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
ocamlyacc . . . . . . . . . . . . . . . . . . . . . 303 signal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 590
stream . . . . . . . . . . . . . . . . . . . . 297, 305 signature . . . . . . . . . . . . . . . . . . . . . . . . . . . 410
top-down . . . . . . . . . . . . . . . . . . . . . . 297 constraint . . . . . . . . . . . . . . . . . . . . . . 411
pattern socket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627
character interval . . . . . . . . . . . . . . . 39 stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
combining . . . . . . . . . . . . . . . . . . . . . . 36 standalone executable . . . . . . . . . . . . . . 207
guard . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Stop&Copy . . . . . . . . . . . . . . . . . . . . . . . . . 256
matching . . . . . . . . . . . . . . . . . . . . . . . 34 stream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
Index of concepts 723

lexical analysis . . . . . . . . . . . . . . . . . 289 value


parsing . . . . . . . . . . . . . . . . . . . 297, 305 atomic . . . . . . . . . . . . . . . . . . . . . . . . . . 70
strict (language) . . . . . . . . . . . . . . . . . . . . . 97 construction . . . . . . . . . . . . . . . . . . . 249
string . . . . . . . . . . . . . . see character string declaration . . . . . . . . . . . . . . . . . . . . . . 19
strings exploration . . . . . . . . . . . . . . . . . . . . 323
representation . . . . . . . . . . . . . . . . . 330 function . . . . . . . . . . . . . . . . . . . . . . . 332
structure . . . . . . . . . . . . . . . . . . . . . . . . . . . 410 global declaration . . . . . . . . . . . . . . . 19
subtyping-typage . . . . . . . . . . . . . . . . . . . 465 immediate . . . . . . . . . . . . . . . . . . . . . 325
super . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445 inspection . . . . . . . . . . . . . . . . . . . . . 280
synchronization . . . . . . . . . . . . . . . . . . . . . 604 local declaration . . . . . . . . . . . . . . . . 19
syntax analysis . . . . . . . . . . . . . . . . . . . . . 295 persistent
type . . . . . . . . . . . . . . . . . . . . . . . . . 233
—T— representation . . . . . . . . . . . . . . . . . 323
in C . . . . . . . . . . . . . . . . . . . . . . . . . 318
tag bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 sharing . . . . . . . . . . . . . . . . . . . . . . . . . 69
this . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445 structured . . . . . . . . . . . . . . . . . . 70, 326
thread . . . . . . . . . . . . . . . see processus léger variable
toplevel . . . . . . . . . see boucle d’interaction bound . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Toplevel loop free . . . . . . . . . . . . . . . . . . . . . . . . . 23, 26
directives . . . . . . . . . . . . . . . . . . . . . . 205 type . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
trace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273 weak type . . . . . . . . . . . . . . . . . . . . . . . 75
tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 variants
tuple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 polymorphic . . . . . . . . . . . . . . . . . . . 709
type vector . . . . . . . . . . . . . . . . . . . . . . . . . see array
abstract . . . . . . . . . . . . . . . . . . . . . . . 407 virtual
constraint . . . . . . . . 30, 417, 454, 455 class . . . . . . . . . . . . . . . . . . . . . . . . . . . 450
constructor . . . . . . . . . . . . . . . . . . . . . 34 method . . . . . . . . . . . . . . . . . . . . . . . . 450
declaration . . . . . . . . . . . . . . . . . . . . . . 41
enumerated . . . . . . . . . . . . . . . . . . . . . 45 —Z—
function . . . . . . . . . . . . . . . . . . . . . . . . 49
functional . . . . . . . . . . . . . . . . . . . . . . . 21 Zinc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
mutually recursive . . . . . . . . . . . . . . 42 interpreter . . . . . . . . . . . . . . . . . . . . . 207
object . . . . . . . . . . . . . . . . . . . . . . . . . 450 zombie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586
open . . . . . . . . . . . . . . . . . . . . . . 450, 453
parameterized . . . . . . . . . . . 30, 42, 48
product . . . . . . . . . . . . . . . . . . . . . . . . . 41
record . . . . . . . . . . . . . . . . . . . . . . . . . . 43
recursive . . . . . . . . . . . . . . . . . . . . . . . . 47
sum . . . . . . . . . . . . . . . . . . . . . . . . . 41, 45
sum types
representation . . . . . . . . . . . . . . . 330
union . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

—U—
UML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439

—V—
724 Index of concepts
Index of language
elements
— Symboles — ¿} . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470
¿ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
& . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706
&& . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 [] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
[< . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 709 # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440, 454
[> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 709 % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 ˆ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
** . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 704
* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13, 17 { ¡ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 ‘ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 709
+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 —— . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
-. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
-¿ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
- . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
—A—
/. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 accept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 630
/ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 acos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
:: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 add available units . . . . . . . . . . . . 242
:= . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 add interfaces . . . . . . . . . . . . . . . . . . 242
:¿ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465 alarm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 592
: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30, 704 alloc.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 allow unsafe modules . . . . . . . . . . 242
¡- . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69, 72, 73 and (keyword) . . . . . . . . . . . . . . . . . . . 20, 42
¡= . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 append . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
¡¿ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Arg (module) . . . . . . . . . . . . . . . . . . . . . . . 236
¡ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 argv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
== . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Arith status (module) . . . . . . . . . . . 240
= . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Array (module) . . . . . . . 68, 217, 218, 221
¿= . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 array (type) . . . . . . . . . . . . . . . . . . . . . . . . 68
726 Index of language elements

as (keyword) . . . . . . . . . . . . . . 38, 454, 699 create process . . . . . . . . . . . . . . . . . . 581


asin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 current point . . . . . . . . . . . . . . . . . . . . 120
assoc . . . . . . . . . . . . . . . . . . . . . . . . . 151, 221
assq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
atan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
—D—
delay . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603
—B— Delayed . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
descr of in channel . . . . . . . . . . . 577
background . . . . . . . . . . . . . . . . . . . . . . . . 120 descr of out channel . . . . . . . . . . 577
big int (type) . . . . . . . . . . . . . . . . . . . . 240 Digest (module) . . . . . . . . . . . . . . 223, 227
bind . . . . . . . . . . . . . . . . . . . . . . . . . . 627, 629 do (keyword) . . . . . . . . . . . . . . . . . . . . . . . . 81
blit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 done (keyword) . . . . . . . . . . . . . . . . . . . . . . 81
blit image . . . . . . . . . . . . . . . . . . . . . . . 125 downto (keyword) . . . . . . . . . . . . . . . . . . . 81
bool (type) . . . . . . . . . . . . . . . . . . . . . . . . . . 15 draw arc . . . . . . . . . . . . . . . . . . . . . . . . . . 121
bprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 draw circle . . . . . . . . . . . . . . . . . . . . . . 121
broadcast . . . . . . . . . . . . . . . . . . . . . . . . . 609 draw ellipse . . . . . . . . . . . . . . . . . . . . . 121
Buffer (module) . . . . . . . . . . . . . . . . . . . 217 draw image . . . . . . . . . . . . . . . . . . . . . . . 125
button down . . . . . . . . . . . . . . . . . . . . . . 133 dump image . . . . . . . . . . . . . . . . . . . . . . . 125
dup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
—C— dup2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
Dynlink (module) . . . . . . . . . . . . . . . . . . 241
Callback (module) . . . . . . . . . . . . . . . . . 343
catch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
ceil . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 —E—
char (type) . . . . . . . . . . . . . . . . . . . . . . . . . . 15
else (keyword) . . . . . . . . . . . . . . . . . . . . . . 18
char of int . . . . . . . . . . . . . . . . . . . . . . 15
end (keyword) . . . . . . . . . . . . . . . . . 410, 437
chdir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
End of file . . . . . . . . . . . . . . . . . . . . . . 76
check . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
eprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
class (keyword) . . . . . . . . . . . . . . . . . . . 437
error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
clear available units . . . . . . . . . 242
error (type) . . . . . . . . . . . . . . . . . . . . . . . 573
clear graph . . . . . . . . . . . . . . . . . . . . . . 119
error message . . . . . . . . . . . . . . . . . . . . 573
close . . . . . . . . . . . . . . . . . . . . . . . . . 576, 629
establish server . . . . . . . . . . . . . . . . 633
close graph . . . . . . . . . . . . . . . . . . . . . . 119
Event (module) . . . . . . . . . . . . . . . . . . . . 612
close in . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
close out . . . . . . . . . . . . . . . . . . . . . . . . . . 77
exception (keyword) . . . . . . . . . . . . . . . . 55
close process . . . . . . . . . . . . . . . . . . . . 589
exists . . . . . . . . . . . . . . . . . . . . . . . . . 51, 220
color (type) . . . . . . . . . . . . . . . . . . . . . . . 120
exit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603
combine . . . . . . . . . . . . . . . . . . . . . . . 151, 221
exn (type) . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
command . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
exp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
compact . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
external (keyword) . . . . . . . . . . . . . . . . 318
concat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
Condition (module) . . . . . . . . . . . . . . . . 609
connect . . . . . . . . . . . . . . . . . . . . . . . 627, 630 —F—
constraint (keyword) . . . . . . . . . . . . . 455 failwith . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
copy . . . . . . . . . . . . . . . . . . . . . . . . . . 222, 471 false . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
cos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
create . . . . . . 68, 222, 265, 602, 604, 609 file exists . . . . . . . . . . . . . . . . . . . . . . 234
create image . . . . . . . . . . . . . . . . . . . . . 125 Filename (module) . . . . . . . . . . . . . . . . . 238
Index of language elements 727

fill . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 host entry (type) . . . . . . . . . . . . . . . . 626


fill poly . . . . . . . . . . . . . . . . . . . . . . . . 121
fill rect . . . . . . . . . . . . . . . . . . . . . . . . 121
filter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
—I—
find . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 if (keyword) . . . . . . . . . . . . . . . . . . . . . . . . 18
find all . . . . . . . . . . . . . . . . . . . . . . . . . . 221 ignore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
flatten . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
float (type) . . . . . . . . . . . . . . . . . . . . . . . . 13 in (keyword) . . . . . . . . . . . . . . . . . . . . . . . . 20
float of string . . . . . . . . . . . . . . . . . . 15 in channel . . . . . . . . . . . . . . . . . . . . . . . . 76
floor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 in channel of descr . . . . . . . . . . . 577
fold left . . . . . . . . . . . . . . . . . . . . . 51, 219 inet addr (type) . . . . . . . . . . . . . . . . . . 625
fold right . . . . . . . . . . . . . . . . . . . . . . . 219 inet addr of string . . . . . . . . . . . 626
for (keyword) . . . . . . . . . . . . . . . . . . . . . . . 81 init . . . . . . . . . . . . . . . . . . . . . . . . . . 178, 242
for all . . . . . . . . . . . . . . . . . . . . . . . 26, 220 initializer (keyword) . . . . . . . . . . . . 448
force . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
foreground . . . . . . . . . . . . . . . . . . . . . . . . 120 input line . . . . . . . . . . . . . . . . . . . . . . . . 77
Format (module) . . . . . . . . . . . . . . . . . . . 223 int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
format (type) . . . . . . . . . . . . . . . . . 224, 226 int (type) . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
fprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 int of char . . . . . . . . . . . . . . . . . . . . . . 15
from channel . . . . . . . . . . . . . . . . . . . . . 229 int of string . . . . . . . . . . . . . . . . . . . . 15
from string . . . . . . . . . . . . . . . . . . . . . . 229 interactive . . . . . . . . . . . . . . . . . . . . . . . 234
fst . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 iter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
full major . . . . . . . . . . . . . . . . . . . . . . . 263 iter2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
fun (keyword) . . . . . . . . . . . . . . . . . . . . . . . 23 iteri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
function (keyword) . . . . . . . . . . . . . . . . . 21
functor (keyword) . . . . . . . . . . . . . . . . . 418 —K—
key pressed . . . . . . . . . . . . . . . . . . . . . . 133
—G— kill . . . . . . . . . . . . . . . . . . . . . . . . . . 590, 603
Gc (module) . . . . . . . . . . . . . . . . . . . . . . . . 263
Genlex (module) . . . . . . . . . . . . . . . . . . . 288 —L—
get . . . . . . . . . . . . . . . . . . . . . . . 218, 263, 265
get image . . . . . . . . . . . . . . . . . . . . . . . . 125 labltk (command) . . . . . . . . . . . . . . . . . 712
getcwd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 Lazy (module) . . . . . . . . . . . . . . . . . . . . . 108
getenv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 lazy (keyword) . . . . . . . . . . . . . . . . . . . . . 108
gethostbyaddr . . . . . . . . . . . . . . . . . . . . . 626 length . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
gethostbyname . . . . . . . . . . . . . . . . . . . . . 626 let (keyword) . . . . . . . . . . . . . . . . . . . 19, 20
gethostname . . . . . . . . . . . . . . . . . . . . . . . 626 lexbuf (type) . . . . . . . . . . . . . . . . . . . . . . 293
getservbyname . . . . . . . . . . . . . . . . . . . . . 627 Lexing (module) . . . . . . . . . . . . . . . . . . . 293
getservbyport . . . . . . . . . . . . . . . . . . . . . 627 lineto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
global replace . . . . . . . . . . . . . . . . . . 292 List (module) . . . . . . . . 18, 217, 218, 220
Graphics (module) . . . . . . . . . . . . . . . . . 117 list (type) . . . . . . . . . . . . . . . . . . . . . . . . . . 17
listen . . . . . . . . . . . . . . . . . . . . . . . . 627, 630
loadfile . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
—H— loadfile private . . . . . . . . . . . . . . . . 242
handle error . . . . . . . . . . . . . . . . . . . . . 573 lock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604
Hashtbl (module) . . . . . . . . . . . . . 217, 227 log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
hd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18, 220 log10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
728 Index of language elements

lseek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577 ocaml (command) . . . . . . . . . . . . . 201, 205


ocamlbrowser (command) . . . . . . . . . . 712
—M— ocamlc (command) . . . . . . . 201, 202, 204
ocamlc.opt (command) . . . . . . . . . . . . 201
major . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 ocamldebug (command) . . . . . . . . . . . . 278
make . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 ocamldep (command) . . . . . . . . . . . . . . 272
make image . . . . . . . . . . . . . . . . . . . . . . . 125 ocamllex (command) . . . . . . . . . . 293, 311
make lexer . . . . . . . . . . . . . . . . . . . . . . . 289 ocamlmktop (command) . . 118, 201, 206
make matrix . . . . . . . . . . . . . . . . . . . . . . 222 ocamlopt (command) . . . . . . . . . . . . . . 201
Map (module) . . . . . . . . . . . . . . . . . . . . . . . 420 ocamlopt.opt (command) . . . . . . . . . . 201
map . . . . . . . . . . . . . . . . . . . . . . . . . 26, 51, 218 ocamlrun (command) . . . . . . . . . . 201, 207
map2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 ocamlyacc (command) . . . . . . . . 303, 311
mapi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 of (keyword) . . . . . . . . . . . . . . . . . . . . . . . . 45
Marshal (module) . . . . . . . . . . . . . 223, 229 of channel . . . . . . . . . . . . . . . . . . . . . . . 111
match (keyword) . . . . . . . . . . . . . . . . 34, 111 of list . . . . . . . . . . . . . . . . . . . . . . 150, 223
Match Failure . . . . . . . . . . . . . . . . . . . . . 36 of string . . . . . . . . . . . . . . . . . . . . . . . . 111
matched string . . . . . . . . . . . . . . . . . . 292 open (keyword) . . . . . . . . . . . . . . . . 214, 409
max array length . . . . . . . . . . . . . . . 234 open connection . . . . . . . . . . . . . . . . . 635
mem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53, 220 open flag (type) . . . . . . . . . . . . . . . . . . 575
mem assoc . . . . . . . . . . . . . . . . . . . . . . . . 221 open graph . . . . . . . . . . . . . . . . . . . . . . . 119
mem assq . . . . . . . . . . . . . . . . . . . . . . . . . . 221 open in . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
memory.h . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 open out . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
memq . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53, 220 open process . . . . . . . . . . . . . . . . . . . . . 589
method (keyword) . . . . . . . . . . . . . . . . . . 437 openfile . . . . . . . . . . . . . . . . . . . . . . . . . . . 575
minor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 option (type) . . . . . . . . . . . . . . . . . . . . . . 265
mkfifo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588 or . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
mlvalues.h . . . . . . . . . . . . . . . . . . . . . . . . 323 OS type . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
mod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
out channel . . . . . . . . . . . . . . . . . . . . . . . 76
module (keyword) . . . . . . . . . . . . . . . . . . 410 out channel of descr . . . . . . . . . . 577
module type (keyword) . . . . . . . . . . . . 410 output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
mouse pos . . . . . . . . . . . . . . . . . . . . . . . . 133
moveto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
mutable (keyword) . . . . . . . . . . . . . . . . . . 73 —P—
Mutex (module) . . . . . . . . . . . . . . . . . . . . 604 parse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
parser (keyword) . . . . . . . . . . . . . 111, 290
—N— partition . . . . . . . . . . . . . . . . . . . . . . . . . 221
Pervasives (module) . . . . . . . . . . . . . . 215
new (keyword) . . . . . . . . . . . . . . . . . . . . . . 440 pipe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 587
next . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 plot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
None . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 point color . . . . . . . . . . . . . . . . . . . . . . 120
not . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 print . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
nth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 print newline . . . . . . . . . . . . . . . . . . . . . 78
Num (module) . . . . . . . . . . . . . . . . . . . . . . . 239 print stat . . . . . . . . . . . . . . . . . . . . . . . 263
num (type) . . . . . . . . . . . . . . . . . . . . . . . . . . 240 print string . . . . . . . . . . . . . . . . . . . . . . 78
Printexc (module) . . . . . . . . . . . . . . . . . 238
—O— Printf (module) . . . . . . . . . . . . . . . . . . . 223
printf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
object (keyword) . . . . . . . . . . . . . . . . . . 437
Index of language elements 729

private (keyword) . . . . . . . . . . . . . . . . . 449 sigint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 592


process status (type) . . . . . . . . . . . . 586 signal . . . . . . . . . . . . . . . . . . . . . . . . 591, 609
signal behavior (type) . . . . . . . . . . 591
—Q— sigusr1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 593
sigusr2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 593
Queue (module) . . . . . . . . . . . . . . . . . . . . 217 sin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
sleep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 584
—R— snd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
SOCK STREAM . . . . . . . . . . . . . . . . . . . . . . 628
raise (keyword) . . . . . . . . . . . . . . . . . . . . 56 sockaddr (type) . . . . . . . . . . . . . . . . . . . . 629
Random (module) . . . . . . . . . . . . . . . . . . . 216 socket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 628
ratio (type) . . . . . . . . . . . . . . . . . . . . . . . 240 socket (type) . . . . . . . . . . . . . . . . . . . . . . 627
read . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576 socket domain (type) . . . . . . . . . . . . . 628
read key . . . . . . . . . . . . . . . . . . . . . . . . . . 133 socket type (type) . . . . . . . . . . . . . . . 628
read line . . . . . . . . . . . . . . . . . . . . . . . . . . 78 Some . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
rec (keyword) . . . . . . . . . . . . . . . . . . . . . . . 27 Sort (module) . . . . . . . . . . . . . . . . . . . . . 217
receive . . . . . . . . . . . . . . . . . . . . . . . . . . . . 612 split . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
-rectypes . . . . . . . . . . . . . . . . . . . . . . . . . 701 sprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
ref (type) . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 sqrt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
regexp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292 Stack (module) . . . . . . . . . . . . . . . . 217, 406
register . . . . . . . . . . . . . . . . . . . . . . . . . . . 343 Stack overflow (exception) . . . . . . . . 95
remove . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 stat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
remove assoc . . . . . . . . . . . . . . . . . . . . . 221 status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
remove assq . . . . . . . . . . . . . . . . . . . . . . 221 stderr . . . . . . . . . . . . . . . . . . . . . . . . . 76, 573
rename . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 stdin . . . . . . . . . . . . . . . . . . . . . . . . . . 76, 573
rev . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 stdout . . . . . . . . . . . . . . . . . . . . . . . . . 76, 573
rev append . . . . . . . . . . . . . . . . . . . . . . . 220 Str (module) . . . . . . . . . . . . . . . . . . . . . . . 292
rgb (type) . . . . . . . . . . . . . . . . . . . . . . . . . . 120 Stream (module) . . . . . . . . . . . . . . . . . . . 110
stream (type) . . . . . . . . . . . . . . . . . . . . . . 110
—S— String (module) . . . . . . . . . . . . . . . . . . . 217
string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
search forward . . . . . . . . . . . . . . . . . . 292 string (type) . . . . . . . . . . . . . . . . . . . . . . . 15
seek command (type) . . . . . . . . . . . . . . 577 string of float . . . . . . . . . . . . . . . . . . 15
send . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 612 string of inet addr . . . . . . . . . . . 626
service entry (type) . . . . . . . . . . . . . 627 string of int . . . . . . . . . . . . . . . . . . . . 15
Set (module) . . . . . . . . . . . . . . . . . . . . . . . 420 struct (keyword) . . . . . . . . . . . . . . . . . . 410
set . . . . . . . . . . . . . . . . . . . . . . . 221, 263, 265 sub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
set binary mode in . . . . . . . . . . . . 577 sync . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 612
set binary mode out . . . . . . . . . . . 577 Sys (module) . . . . . . . . . . . . . . . . . . . . . . . 234
set color . . . . . . . . . . . . . . . . . . . . . . . . 120 Sys error . . . . . . . . . . . . . . . . . . . . . . . . . . 77
set font . . . . . . . . . . . . . . . . . . . . . . . . . . 120
set line . . . . . . . . . . . . . . . . . . . . . . . . . . 120
set signal . . . . . . . . . . . . . . . . . . . . . . . 591 —T—
set text size . . . . . . . . . . . . . . . . . . . 120 tan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
shutdown connection . . . . . . . . . . . . . 635 then (keyword) . . . . . . . . . . . . . . . . . . . . . . 18
sig (keyword) . . . . . . . . . . . . . . . . . . . . . . 410 Thread (module) . . . . . . . . . . . . . . . . . . . 602
sigalrm . . . . . . . . . . . . . . . . . . . . . . . . . . . . 592 ThreadUnix (module) . . . . . . . . . . . . . . 639
sigchld . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594
730 Index of language elements

time . . . . . . . . . . . . . . . . . . . . . . . . . . 178, 234


tl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18, 220
to (keyword) . . . . . . . . . . . . . . . . . . . . . . . . 81
to buffer . . . . . . . . . . . . . . . . . . . . . . . . 229
to channel . . . . . . . . . . . . . . . . . . . . . . . 229
to list . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
to string . . . . . . . . . . . . . . . . . . . . 229, 238
token (type) . . . . . . . . . . . . . . . . . . . . . . . 288
#trace (directive) . . . . . . . . . . . . . . . . . . 273
true . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
try (keyword) . . . . . . . . . . . . . . . . . . . . . . . 56
try lock . . . . . . . . . . . . . . . . . . . . . . . . . . 604
type (keyword) . . . . . . . . . . . . . . . . . . . . . . 41

—U—
unit (type) . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Unix (module) . . . . . . . . . . . . . . . . . . . . . 572
Unix error . . . . . . . . . . . . . . . . . . . . . . . 573
unlock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604
#untrace (directive) . . . . . . . . . . . . . . . . 273
#untrace all (directive) . . . . . . . . . . 273

—V—
val (keyword) . . . . . . . . . . . . . . . . . 408, 437
val mutable (keyword) . . . . . . . . . . . . 437
Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
value . . . . . . . . . . . . . . . . . . . . . . . . . 318, 324
virtual (keyword) . . . . . . . . . . . . . . . . . 450

—W—
wait . . . . . . . . . . . . . . . . . . . . . . . . . . 585, 609
wait next event . . . . . . . . . . . . . . . . 132
wait time read . . . . . . . . . . . . . . . . . . 646
wait time write . . . . . . . . . . . . . . . . 646
waitpid . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586
Weak (module) . . . . . . . . . . . . . . . . . 217, 265
when (keyword) . . . . . . . . . . . . . . . . . . . . . . 38
while (keyword) . . . . . . . . . . . . . . . . . . . . 81
with (keyword) . . . . . 34, 44, 56, 111, 417
word size . . . . . . . . . . . . . . . . . . . . . . . . 234
write . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
Liste de diffusion par messagerie électronique
Si vous souhaitez recevoir périodiquement les annonces de nouveaux produits O’Reilly
en français, il vous suffit de souscrire un abonnement à la liste d’annonces

parutions-oreilly

Merci d’expédier en ce cas un message électronique à majordomo@ora.de contenant


(dans le corps du message) :

subscribe parutions-oreilly votre_adresse_email

Exemple :

subscribe parutions-oreilly jean.dupond@ici.fr

Cette liste ne véhicule que des annonces et non des discussions, vous ne pourrez par
conséquent pas y poster. Son volume ne dépasse pas quatre messages par mois.
En cas de problème technique écrire à

parutions-oreilly-owner@ora.de

Site Web
Notre site Web http://www.editions-oreilly.fr/ diffuse diverses informations :

• le catalogue des produits proposés par les éditions O’Reilly,


• les errata de nos ouvrages,
• des archives abritant les exemples,
• la liste des revendeurs.

Vous aimerez peut-être aussi