Cours alternatif d’OCaml

Logo OCaml
I — Notions de base

Les fonctions

Comme nous l’avons dit un peu plus tôt, les fonctions sont au centre du langage OCaml. Ça tombe bien, nous allons voir comment en créer, et comment en appeler.

Créer une fonction

En OCaml, on utilise le mot-clé let pour définir une fonction :

let f x y = x + y

Pour mieux voir à quoi ce code correspond, voici un équivalent en Python :

def f(x, y):
    return x + y

On remarque plusieurs différences :

Cette syntaxe minimaliste peut sembler un peu étrange au premier abord, mais on s’y habitue rapidement, et elle s’avère très pratique quand on commence à faire du OCaml à un niveau un peu plus avancé (c.f. la section bonus).

Si on tape cette commande dans l’interpréteur OCaml, on peut obtenir le type de la fonction :

f

On voit donc que cette fonction a un type elle aussi : int -> int -> int. Ce qu’il faut savoir sur cette notation, c’est que les premiers types sont ceux des arguments, et le dernier celui de la valeur de retour. Ici, les deux arguments x et y sont bien des int, et leur addition est bien un int aussi. Si vous voulez comprendre pourquoi cette notation qui semble peu intuitive a été choisie, on en reparlera dans le chapitre sur la curryfication.

Une bonne pratique (c’est même demandé lors des examens à l’UGA), est de noter explicitement le type de ses fonctions. Pour cela, on utilise la syntaxe (argument : type) à la place de juste argument. Et pour la valeur de retour, on indique son type avec : type juste avant le =.

let f (x : int) (y : int) : int = x + y

Cette notation est plus longue, mais elle a l’avantage de rendre explicite les types des différentes expressions. Ainsi, il est plus simple de raisonner sur cette fonction, car on voit clairement quelles valeurs les arguments et la valeur retournée peuvent prendre.

Petite astuce : les définitions multiples

Vous pouvez aussi définir plusieurs fonctions à la fois, en séparant leurs déclarations par un and (qui n’a rien à voir avec un &&, attention) :

let identite x = x and carre x = x * x and cube x = x * x * x

Mais avec cette syntaxe, on ne peut pas utiliser les fonctions qu’on a définies juste avant dans les définitions de la même ligne. Par exemple, on n’aurait pas pu écrire :

let carre x = x * x and cube x = (carre x) * x

Car la fonction carre n’existe pas encore vraiment quand on l’utilise dans la définition de cube.

Appeler une fonction

Maintenant que nous avons une première fonction (n’hésitez pas à en créer d’autres d’ailleurs), voyons comment l’appeler.

f 1 2

Et voilà ! Normalement, l’interpréteur vous a bien répondu avec un 3. Si vous avez besoin de passer des expressions plus complexes en arguments, vous pouvez les entourer de parenthèses :

f (4 * 3) 7 (* Donne 19 *)

Et les variables ?

Le concept de variable n’existe pas réellement en OCaml1. Cependant, on peut avoir des constantes, avec des fonctions sans arguments :

let pi = 3.1415

De plus, on peut définir des fonctions uniquement de façon locale, en les limitant à une expression. Pour celà, après la déclaration de la fonction, on ajoute le mot-clé in, et une expression dans laquelle on pourra utiliser la fonction qu’on vient de définir.

let cube x = x * x * x in (cube 2) + (cube 3)

(* Sans définir cube auparavant, on aurait dû écrire : *)
(2 * 2 * 2) + (3 * 3 * 3)

En général, on met un retour à la ligne après un in pour rendre le code plus lisible. Il est donc possible d’imbriquer les let et les let/in :

(* Cette fonction donne la norme d’un vecteur 2D, à partir de ses coordonnées *)
let norme (x : float) (y : float) : float =
  let carre a = a * a in
  let x_carre = carre x in
  let y_carre = carre y in
  sqrt (x_carre + y_carre) (* sqrt est une fonction de base d’OCaml *)

  1. En réalité, le concept de référence y correspond à peu près, mais on évite de l’utiliser, et nous n’en parlerons pas dans ce cours.