Outils pour utilisateurs

Outils du site


nsi:langages:ocaml:fonctions

Fonctions

Évidemment, dans un langage fonctionnel, cette partie est très importante.

let f = fun x -> x+1;;
(* affiche : val f: int -> int = <fun> *)

On a assigner à f une fonction en utilisant le mot-clé fun. Cette fonction est comme une fonction mathématique, elle consiste en l'association d'un item à un autre.

La fonction est ici reconnue comme associant un entier à un entier.

On pourra calculer :

f 5;; (*affiche 6*)
f(5);; (*idem*)

Fonction à plusieurs variables

Une fonction à deux variables devient un peu plus bizarre :

let g = fun x y -> x * y;;
(* renvoie val g: int -> int -> int <fun> *)
g 4 13;; (* renvoie 52 *)
g(4,13);; (* Erreur ! *)
g 4;; (* renvoie une fonction int -> int ??? *)
g(4);; (* idem *)
g(4)(13);; (* renvoie 52 *)

Il faut comprendre que la fonction g reçoit d'abord l'argument x, disons x = 4 pour l'exemple. x étant connu, on sait que le résultat sera 4 * y.

g 4 produit donc une fonction y → 4 * y.

Puisque g(4) est une la fonction y → 4 * y on peut lui appliquer un argument : g(4)(13) qui fait 52.

Remarquez que les parenthèses sont inutiles et ne servent qu'à préciser une priorité en cas de besoin.

Par exemple :

f f 5;; (* Erreur : le premier f essaie de prendre le 2e f comme argument *)
f (f 5);; (* Ok : le premier f prendra le résultat de (f 5) comme argument *)

Fonction comme argument

Une fonction peut avoir une une fonction comme argument. Par exemple, on pourrait définir une fonction repete consistant, à partir d'une fonction $x \mapsto f(x)$ d'obtenir la fonction $x \mapsto f(f(x))$.

let repete f = fun x -> f ( f x );;
(* equivalent a : *)
let repete f x = f ( f x ) ;;

(* Exemple : *)
let g = fun x -> 3 * x + 2;;
let h = repete g;;
(* g est la fonction x -> g(g(x)) *)
g(1);; (* renvoie 5 *)
g(5);; (* renvoie 17 *)
h(1);; (* renvoie g(g(1)), soit 17 *)

Cas de la récurrence

OCaml autorise les fonctions récurrentes mais il faut alors préciser le mot clé rec.

Par exemple, le classique factoriel :

let rec facto = fun n -> if n > 1 then n * (facto (n-1) ) else 1;;

La récurrence est le chemin privilégié. Supposez que vous souhaitiez faire la somme des n premiers entiers. Il serait naturel d'écrire

(* attention code faux *)
let n = 10;;
let t = 0;;
for i = 1 to n do
  t = t + i;
done;;
t;;

Mais cela ne fonctionne pas : La commande t = t + i suppose de modifier la valeur de t ce qui n'est en principe pas possible ! Il faut passer par une récurrence :

let rec somme = fun n -> if n = 0 then 0 else n + somme(n-1);;
somme 10;;

La boucle est alors contenue dans l'utilisation de la récurrence.

Bien sûr une récursion terminale est bienvenue :

let rec somme_rec = fun n s -> if n = 0 then s else somme_rec(n-1, s);;
let somme = fun n -> somme_rec n 0

Définition par cas

La fonction somme précédente prévoyait deux cas : n = 0 ou n quelconque. Il pourrait y avoir plus de cas et OCaml prévoit une syntaxe pour cela :

let rec somme = function
  | 0 -> 0 
  | n -> n + somme(n-1) ;;

Il suffit d'énumérer les cas possibles et d'indiquer quoi faire à chaque fois.

nsi/langages/ocaml/fonctions.txt · Dernière modification : de goupillwiki