Caml offre les structures de données suivantes: les nombres (entiers ou flottants), les booléens, les caractères, les chaînes de caractères, les tableaux, les listes, les références. La bibliothèque standard définit aussi des structures de données plus complexes, par exemple les ensembles et les flux, voir plus bas.
Si aucune de ces structures de données ne répond à votre problème, il vous faut définir vos propres structures de données, à l'aide de définitions de type.
Table des matières:
Les nombres entiers et flottants correspondent à l'arithmétique de la machine. Ces nombres sont donc faciles à utiliser mais souffrent de certaines limitations dues au matériel, soit en ce qui concerne la précision, soit en ce qui concerne la taille. Caml vous offre aussi des nombres qui ne présentent pas ces limitations: la bibliothèque d'arithmétique en grande précision implémente des nombres rationnels, dont la taille peut croître jusqu'à plusieurs milliers de chiffres décimaux. Cette arithmétique rationnelle est plus délicate à utiliser que l'arithmétique standard de la machine.
int
et sont
munis des opérations usuelles: +, -, *, / (qui rend le quotient entier
de la division).
#1 + 2 * 3;; - : int = 7
Autres opérations:
print_int
.
lsl
(logical shift left), lsr
(logical
shift right), asr
(arithmetic
shift right), land
(et), lor
(ou),
lxor
(ou exclusif), lnot
(non).
int
: int_of_string
,
int_of_float
, int_of_char
.
int
.
float
et sont munis des opérations usuelles
(suffixées par un .
):
+.
, -.
, *.
, /.
#1.0 +. 2.0 *. 3.0;; - : float = 7.0
Autres opérations:
print_float
.
sin
, cos
, tan
,
asin
, acos
, atan
,
atan2
, exp
, log
,
**
.
float_of_string
,
float_of_int
.
float
.
Les caractères sont les éléments du type char
. On les
note en entourant le caractère par le symbole `
:
#`a`;; - : char = `a` #`\n`;; - : char = `\n` #`\\`;; - : char = `\\`
Autres opérations:
print_char
.
char_of_int
,
char_for_read
char
.
Les chaînes de caractères sont les éléments du type
string
; ce sont des suites ordonnées de lettres. La
taille d'une chaîne de caractères est fixée à la création de la
chaîne. Les éléments d'une chaîne de caractères sont modifiables.
"
.
#let s = "ok";; s : string = "ok"
#let s1 = make_string 2 `1`;; s1 : string = "11" #s1.[1] <- `2`;; - : unit = () #s1;; - : string = "12"
str.[i]
renvoie le caractère numéro i
de la
chaîne str
.
#let s = "ok";; s : string = "ok" #s.[0];; - : char = `o` #s.[1];; - : char = `k`
str.[i] <-
char
, met le caractère char à la case i
de la chaîne str
:
#let s = "ok";; s : string = "ok" #s.[1] <- `h`;; - : unit = () #s;; - : string = "oh"
#let s = "ok";; s : string = "ok" #for i = 0 to string_length s - 1 do print_char s.[i]; print_string " " done;; o k - : unit = ()
print_string
.
string_length
.
blit_string
.
sub_string
.
string_of_int
,
string_of_float
, string_of_bool
,
string_for_read
, char_for_read
.
^
''.
string
.
Les tableaux ou vecteurs sont les éléments du
type 'a vect
; ce sont des suites ordonnées d'éléments
du type 'a
. La taille d'un tableau est fixée à la
création du tableau. Les éléments d'un tableau sont modifiables.
;
et entourés par les symboles
[|
et |]
.
#let v = [| 1; 2; 3 |];; v : int vect = [|1; 2; 3|]
#let v1 = make_vect 2 "Hello";; v1 : string vect = [|"Hello"; "Hello"|] #v1.(1) <- "World!";; - : unit = () #v1;; - : string vect = [|"Hello"; "World!"|]Attention: la valeur d'initialisation est physiquement partagée entre tous les éléments du vecteur. Si cette valeur d'initialisation est une valeur mutable, ce comportement est parfois surprenant pour le débutant. C'est le cas en particulier pour les matrices, qu'on définit comme des vecteurs de vecteurs: sans précaution, on obtient une matrice dont toutes les cases comporte la même ligne.
tab.(i)
renvoie l'élément numéro i
du
tableau tab
.
#v.(0);; - : int = 1
tab.(i) <-
elem
, met la valeur elem
à la case
i
du tableau tab
.
#v.(1) <- 0;; - : unit = () #v;; - : int vect = [|1; 0; 3|]
#for i = 0 to vect_length v1 - 1 do print_string v1.(i); print_string " " done;; Hello World! - : unit = ()
for
ou la fonctionnelle
do_vect
.
vect_length
.
blit_vect
.
sub_vect
.
concat_vect
.
map_vect
, do_vect
,...
vect
.
Les listes sont les éléments du type 'a list
; ce sont des
suites ordonnées d'éléments du type 'a
. La taille d'une
liste évolue dynamiquement, puisqu'on peut lui ajouter des éléments si
nécessaire. Une liste est une structure de données récursive: elle est
soit vide, et c'est alors []
(qu'on prononce ``nil''), ou
bien elle ne l'est pas et elle est alors formée d'une ``tête'' de
liste, placée devant le ``reste'' (ou queue) de la liste. Une liste
non vide est formée par application du constructeur de liste
::
(opérateur infixe qu'on prononce ``conse''). Une liste
non vide de tête ``x'' et de queue ``rest'' est donc de la forme
x :: rest
. Les éléments d'une liste ne sont pas modifiables.
[
et ]
.
#let l = [ 1; 2; 3 ];; l : int list = [1; 2; 3]
#match l with x :: _ -> x | _ -> raise (Failure "empty");; - : int = 1 #let rec nth n l = match l with [] -> raise (Failure "nth") | x :: l -> if n <= 0 then x else nth (n - 1) l;; nth : int -> 'a list -> 'a = <fun> #nth 2 l;; - : int = 3
[]
), et on ajoute progressivement les éléments de la liste.
#let l1 = [];; l1 : 'a list = [] #let l2 = "World!" :: l1;; l2 : string list = ["World!"] #let l3 = "Hello" :: l2;; l3 : string list = ["Hello"; "World!"] #let rec interval n m = if n > m then [] else n :: interval (n + 1) m;; interval : int -> int -> int list = <fun> #interval 3 7;; - : int list = [3; 4; 5; 6; 7]
#let rec print_list = function [] -> () | x :: l -> print_string x; print_string " "; print_list l in print_list l3;; Hello World! - : unit = ()
do_list
.
list_length
.
@
''.
map
, it_list
,
list_it
, ...
[]
ou filtre x :: l
.
list
.
Les booléens sont les éléments du type
bool
; ce sont les valeurs de la logique booléenne
true
et false
. Ce sont les résultats
rendu par les tests.
#1 = 2;; - : bool = false #1 <= 2;; - : bool = true
Les opérations définies sur les booléens sont les opérations infixes
``ou'' et ``et'' de la logique (opérateurs notés respectivement
||
et &&
),
et la négation (fonction not
).
#(1 = 2) || not (1 <= 2);; - : bool = false #1 = 2 || not 1 <= 2;; - : bool = false
Autres opérations:
print_bool
avec
let print_bool b = print_string (string_of_bool b);;
.
string_of_bool
, bool_of_string
avec
let bool_of_string = function | "true" -> true | "false" -> false | _ -> raise (Invalid_argument "bool_of_string");;
bool
.
``rien'' est l'unique élément du type
unit
. Il est noté ()
(prononcer ``voïde'')
et sert de résultat et d'argument non significatifs pour les
procédures.
#print_string "Hello World!";; Hello World!- : unit = () #print_newline();; - : unit = ()
Les références sont les éléments du type 'a ref
; ce
sont des cases mémoire contenant une valeur de type
'a
. On les utilise dans la programmation impérative pour
implémenter des accumulateurs. L'élément contenu dans une référence
peut être modifié, c'est-à-dire remplacé par une autre valeur du même
type.
ref
à son contenu initial.
#let r = ref 1;; r : int ref = ref 1
!
(prononcer ``deref''). Ainsi !r
renvoie
le contenu de la référence r
.
#!r;; - : int = 1
r := elem
,
met la valeur elem
dans la référence r
.
#r := 0;; - : unit = () #r;; - : int ref = ref 0
En utilisant une référence et une boucle on peut écrire une version impérative de la fonction factorielle:
#let fact x = let result = ref 1 in for i = 1 to x do result := i * !result done; !result;; fact : int -> int = <fun> #fact 10;; - : int = 3628800
incr
, decr
.
ref
.
Les paires d'une valeur de type
'a
et d'une valeur du type 'b
sont les
éléments du produit cartésien de 'a
et 'b
,
que l'on note 'a * 'b
en Caml.
#let p = (1, 2);; p : int * int = 1, 2
#let first = function (x, y) -> x;; first : 'a * 'b -> 'a = <fun> #first p;; - : int = 1
pair
Les autres structures de données disponibles dépendent du système Caml. Citons celles de la bibliothèque du système Caml Light:
Contacter l'auteur Pierre.Weis@inria.fr