1.2- Subtilités du OCaml
I. Tests d'égalité
En vérité, en OCaml, on a deux tests d'égalité différents : = et ==, avec l'inégalité correspondante <> et !=.
=et<>sont à utiliser en priorité, ils testent l'égalité structurelle, c'est à dire celle dont on a l'habitude==et!=testent l'égalité physique. Pour les valeurs simples (entiers...) c'est souvent la même chose, mais regardez l'exemple suivant :
Loading editor...
let t1 = [|1; 2; 3|];; let t2 = [|1; 2; 3|];;
Loading editor...
t1 = t2
Loading editor...
t1 == t2
Loading editor...
t1 <> t2
Loading editor...
t1 != t2
On teste si c'est le même tableau vs un tableau avec le même contenu.
II. Polymorphisme
Le polymorphisme, c'est le fait d'avoir un type générique, qui peut se traduire par plusieurs types. En général, si vous voyez apparaitre des 'a, 'b, etc, c'est qu'on a du polymorphisme, et 'a, 'b, ... représentent des types quelconques.
Voici quelques exemples :
Loading editor...
let first couple =
let (t1, _) = couple in t1;;
first (1, 2);;
first ("bonjour", "au revoir");;Cette fonction à le type 'a * 'b -> 'a, c'est à dire qu'elle prend un couple, avec deux éléments de types quelconques, et qu'elle renvoie un élément du type du premier élément du couple.
Loading editor...
let rec len (l: 'a list): int = match l with
|[] -> 0
|_::q -> 1 + len q;;
len [1; 2; 3];;
len ['a'; 'b'];;La fonction a pour type 'a list -> int, donc elle prend en argument une liste quelconque et renvoie un entier.
On peut également définir nos propres types polymorphes :
Loading editor...
type 'a arbre =
| F of 'a
| N of 'a * 'a arbre list;;Ici, on a défini un arbre général qui peut stocker n'importe quel élément : l'arbre est soit
- une feuille contenant un élément de type 'a, c'est à dire quelconque
- un noeud contenant un élément et une liste de 'a arbres
On ne peut pas créer directement un élément de type 'a arbre, il va falloir choisir un type concret.
Loading editor...
let a = N (3, [F 2; F 1])
Ici, on a un int arbre parce que on a mis des entiers à l'intérieur.
Il existe plusieurs types polymorphes déjà définis en OCaml :
- les listes (
'a list) - les tableaux (
'a array) - les références (
'a ref) - les options (
'a option)
Nous n'avons pas vraiment parlé des options : il s'agit d'un type qui sert à représenter une valeur qui peut être présente, ou non.
Elle est définie ainsi :
Loading editor...
type 'a option2 =
|Some2 of 'a
|None2Le type option existe de base en OCaml, vous n'avez pas besoin de le redéfinir. Certaines fonctions renvoient des options.
Loading editor...
let premier l = match l with
|[] -> None
|x::_ -> Some xPlusieurs fonctions de la librairie standard OCaml sont polymorphes :
Loading editor...
max
Loading editor...
min
Loading editor...
fst
Loading editor...
snd
Loading editor...
( @ )
Loading editor...
List.length
III. Fonctions avancées
Fonctions mutuellement récursives
C'est très rarement utile, mais il est possible en OCaml de faire des fonctions mutuellement récursives avec le mot-clé and :
Loading editor...
let rec est_pair n = match n with
| 0 -> true
| 1 -> false
| _ -> est_impair (n-1)
and est_impair n = match n with
| 0 -> false
| 1 -> true
| _ -> est_pair (n-1)Loading editor...
est_pair 126
Fonctions anonymes
On en a déjà un peu parlé, mais on peut écrire des fonctions anonymes avec fun arg1 arg2 ... -> ....
Loading editor...
let plop = fun i -> i + 1;; plop 2
Loading editor...
(fun i -> i + 1) 2
let
Loading editor...
let f ((x, _): 'a * 'b): 'a = x;;
Loading editor...
let f = fun (x, y) -> x;; let f = fun x y -> x
Curryfication
Du mathématicien Haskell Curry, qui n'a pas inventé ce concept (mais qui l'a beaucoup développé).
En OCaml, on peut appeler une fonction avec seulement une partie de ses arguments, et ça nous donne une nouvelle fonction :
Loading editor...
max 3
Loading editor...
let m3 = max 3;;
Loading editor...
m3 10
Loading editor...
m3 1
Cela fonctionne avec toutes les fonctions OCaml ! Et ça peut donner des choses étranges...
Loading editor...
let l = [1; 2; 3; 4; 5];; List.map ((+) 1) l
Ici, (+) est l'équivalent "fonction" de l'opérateur + : c'est une fonction qui additionne ses deux arguments.
Donc, (+) 1 est la fonction qui prend un entier et lui ajoute 1. On peut donc la donner à List.map pour l'appliquer à toute la liste.
IV. Begin ... End
Les mots-clés begin ... end en ocaml agissent exactement comme des parenthèses. On les utilise en général autour des suites d'instructions :
Loading editor...
let print_des_trucs () = begin
print_int 1;
print_newline ();
print_endline "bonjour";
print_char 'a'
endLoading editor...
print_des_trucs ()
Loading editor...