Version sans JavaScript, en lecture seule : les ateliers, les quiz et l’exécution du code n’y sont pas. Version complète · Catalogue · Se connecter

Support de cours · chapitre 3

Fonctions

Définir et appliquer des fonctions, à un ou plusieurs paramètres, et lire leur type.

Fonctions à un seul paramètre

Point sur un programme Caml

Qu'est-ce qu'un programme Caml ?

Définir une fonction

En mathématiques : « Soit successeur la fonction définie par $successeur(x) = x + 1$. »

En Caml :

let successor(x) = x + 1 ;;

Caml répond que successor est une fonction (<fun>), de type int -> int : elle prend un entier et rend un entier. On ne lui a pas donné ce type, il l'a déduit : x + 1 n'a de sens que si x est un entier.

Application d'une fonction

successor(1) ;;

Les parenthèses autour des arguments, aussi bien dans la définition que dans l'application, sont facultatives. On va donc les enlever :

let successor x = x + 1 ;;
successor 4 ;;
successor -1 ;;
successor (-1) ;;

Notation et convention

$$f\,x \equiv \text{application de la fonction } f \text{ à la valeur } x$$

Les applications de fonctions sont implicitement parenthésées et sont prioritaires sur toute autre opération :

$$f\,x + g\,y \equiv (f\,x) + (g\,y)$$
successor 2 * 3 ;;
successor (2 * 3) ;;

La première ligne se lit (successor 2) * 3.

Fonctions prédéfinies

Il existe des fonctions prédéfinies en Caml :

  • sur les flottants : sqrt, sin, exp… ;
  • de conversion : int_of_float, float_of_int, string_of_int… ;
  • dans des modules, qu'on désigne par leur nom suivi d'un point : String.length, Char.code…
sqrt 2.0 ;;
int_of_float 3.7 ;;
string_of_int 42 ;;
String.uppercase_ascii "caml" ;;
Char.code 'a' ;;

Applications de fonctions « imbriquées »

Il est possible de faire des définitions multiples :

let succ x = x + 1
and double x = 2 * x
and square x = x * x ;;

On peut également utiliser le résultat d'une fonction comme paramètre effectif d'une autre (ou de la même) fonction. Notez les parenthèses :

double (square (succ 3)) ;;
let square_of_succ x = square (succ x) ;;
square_of_succ 3 ;;

succ 3 vaut 4, son carré 16, son double 32.

Fonctions et définitions locales

Définition locale de fonction dans une expression

Comme une fonction est une valeur, rien n'empêche de définir une fonction localement, comme nous l'avons fait avec de simples entiers :

let pred x = x - 1 in pred 3 * pred 4 ;;

Définitions locales de valeurs dans les définitions de fonctions

Définissons la fonction square_of_pred, qui retourne le carré du prédécesseur d'un nombre (la fonction $x \longmapsto (x - 1)^2$). Nous définissons localement le prédécesseur de l'argument, puis l'élevons au carré :

let square_of_pred x =
  let pred_x = x - 1 in
  pred_x * pred_x ;;
square_of_pred 5 ;;

Le nom local évite de calculer x - 1 deux fois.

Définition locale de fonction dans une définition globale de fonction

Une fonction peut aussi définir localement une autre fonction :

let cube x =
  let square y = y * y in
  x * square x ;;
cube 3 ;;

square n'existe qu'à l'intérieur de cube.

Utilisations multiples d'une même fonction

Un des intérêts de la définition locale est qu'une fonction déjà définie pourra être utilisée plusieurs fois dans une même expression (ce qui n'était pas le cas dans l'exemple précédent) :

let power4 x =
  let square y = y * y in
  square (square x) ;;
power4 3 ;;

Attention aux parenthèses : square square x appliquerait square à deux arguments, square et x, et Caml le refuserait.

Fonctions à plusieurs arguments

Fonctions à plusieurs arguments

Les fonctions possédant plusieurs arguments ont simplement plusieurs paramètres formels dans leur définition :

let average a b = (a + b) / 2 ;;
average 10 20 ;;
average2 (10, 20) ;;
average (10, 20) ;;

Cas des multi-paramètres

Lorsque des fonctions ont plusieurs arguments, il faut leur fournir tous leurs arguments quand on les applique. Sinon, le résultat n'est pas une erreur, mais une fonction qui attend les arguments manquants :

average 10 ;;

On y reviendra : c'est une propriété importante des fonctions de Caml.

Ici non plus, les parenthèses autour des arguments ne sont pas nécessaires. Toutefois, comme pour une application de fonction à un seul argument, elles deviennent nécessaires lorsqu'un des arguments n'est pas une expression atomique !

average (succ 3) (double 5) ;;

Attention aux parenthèses !

succ (succ 1) ;;
succ succ 1 ;;

succ succ 1 se lit (succ succ) 1 : on applique succ à deux arguments, succ puis 1.