====== Fonctions ====== Évidemment, dans un langage fonctionnel, cette partie est très importante. let f = fun x -> x+1;; (* affiche : val f: int -> int = *) 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 *) 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 [[nsi:terminales:recursivite:cours|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.