Menu1 Menu2 Menu3 Menu4 Menu5 Menu6

Infos pratiques : je vous conseille de lire mes cours en utilisant parallèlement Caml, pour tester vous-mêmes au fur et à mesure. Pour vous simplifier la tâche, j'ai dans tout ce site écrit les lignes de code Caml avec une police différente et un fond blanc au lieu du bleu, pour les détacher du texte normal.
J'ai dans cette page essayé d'être le plus clair possible. Mais apprendre un nouveau langage, surtout si on est novice en informatique, est une tâche rude et beaucoup de choses risquent de vous sembler incompréhensibles. Je vous rassure tout de suite : c'est normal, vous ne devez pas abandonner si vous ne comprenez pas cette page. Moi-même, je n'ai rien compris à mon premier cours d'informatique qui parlait de ce qui suit. Mais quelques jours après, en voyant des exemples et en commençant à manipuler les fonctions, tout s'est éclairé. Si vous ne comprenez pas cette page, je vous conseille donc de regarder le cours exemples de fonctions simples et de revenir après !

Sommaire
Comment fonctionne OCaml ?
Qu'est-ce qu'un module ?
Comment définir un objet ?
Comment définir une fonction ?
Comment évaluer ?
Définition locale
Que signifient les réponses de Caml
Une syntaxe plus simple
Fonctions à plusieurs arguments
Ecrire correctement

I) Commençons par voir comment fonctionne OCaml
Quand vous avez installé ce que vous avez trouvé sur le site de l'INRIA (voir Se procurer OCaml), vous avez en fait installé plusieurs programmes. En fait la plupart sont des compilateurs (il y en a plusieurs car on peut compiler de plusieurs manières, voir le chapitre correspondant). Ces compilateurs suffisent en théorie pour faire un programme : vous l'écrivez, vous le compilez et vous exécutez.
En théorie seulement. Car pendant la phase de création, vous allez probablement faire des erreurs, oublier des paramètres, faire des fautes de frappe, ... A chaque fois que vous voudrez corriger votre programme, vous devrez alors le recompiler et le ré-exécuter. Pas très pratique... En réponse, les concepteurs d'OCaml ont créé ce qu'on appelle la boucle interactive : c'est le programme principal, celui qui si vous avez Windows se nomme « OCamlWin » et se trouve à la racine de votre installation. Si vous êtes sous Linux, c'est le programme qui se lance quand vous tapez « ocaml » dans le terminal.
A quoi sert-il ? Grâce à lui, vous allez pouvoir entrer votre programme instruction par instruction, la boucle d'interaction se chargera à chaque fois de compiler virtuellement puis d'exécuter toute seule ce que vous donnez. Ainsi, vous pouvez faire votre programme étape par étape et apporter directement vos modifications, sans recompiler. Toutefois, cela reste une compilation virtuelle : la boucle interactive ne compile que pour elle-même et ne crée aucun fichier. Une fois que vous avez pu voir que votre programme fonctionnait avec la boucle interactive, vous devez le compiler pour de vrai avec les vrais compilateurs dont j'ai parlé plus haut. La boucle interactive n'est ainsi qu'un outil de développement intermédiaire, mais l'expérience montre que ce n'est pas un luxe !
Un dernier détail : vous pouvez taper votre programme entièrement avec cette boucle car elle permet de les enregistrer (l'extension des programmes Caml est ml) et charger. Toutefois, la conception de la boucle fait que ce fonctionnement est tout sauf pratique : les modifications directes peuvent entraîner des comportements bizarres. Le mieux est en fait de taper votre code dans un éditeur texte indépendant et de faire des copier-coller dans la boucle. Et cela a un autre avantage : bien que vous puissiez utiliser un éditeur simple (par exemple le traditionnel bloc-notes si vous êtes sous Windows), le mieux est sans doute un éditeur qui colore le code : cela vous permet de voir d'un coup d'oeil la structure d'un programme, les parenthèses qui vont ensemble, ... Après, libre à vous de choisir un tel éditeur, il en existe beaucoup. Personnellement, j'utilise Notepad++ qui est libre (pour le télécharger : http://sourceforge.net/project/showfiles.php?group_id=95717&package_id=102072 - choisissez le « Installer.exe »).

II) Les modules
Vous allez voir par la suite que Caml dispose de nombreuses fonctions. Cette fonctions sont regroupées dans ce qu'on appelle des modules ou des librairies, les fichiers que vous pouvez voir dans le répertoire « lib ». Ces modules sont généralement thématiques. Par exemple, le module « List » contient les fonctions pour manipuler... surprise... les listes !
Normalement, si vous souhaitez utiliser une fonction, disons par exemple la fonction « moveto » du module « Graphics », vous allez devoir procéder ainsi :
   - D'abord vous devez dire à OCaml que vous allez utiliser le module Graphics, afin qu'il charge les fonctions correspondantes : pour cela, vous utilisez la directive Load : vous tapez #load "graphics.cma";;.
   Remarque 1 : en Caml les instructions se terminent pas deux points-virgules
   Remarque 2 : l'extension pour le module graphique est « .cma » mais ce n'est pas le cas de tous les modules, cela dépend de la manière dont ils ont été compilés. Pour savoir quelle extension utiliser, regardez dans le répertoire ou consultez le manuel de Caml.
   Remarque 3 : l'important est de charger le module avant l'utilisation des fonctions qui en proviennent et vous pouvez le faire au milieu du programme. L'usage est toutefois de charger tous les modules nécessaires au début : cela permet de voir rapidement quand on reprend un programme quels modules on utilise, ce qui sera important pour la compilation finale.
   - Vous avez alors le droit d'utiliser les fonctions : tapez le nom du module, puis un point, puis le nom de la fonction, par exemple : Graphics.moveto. Attention ! La majuscule pour le module est indispensable.
   - Vous pouvez aller plus loin. En rajoutant la commande open Graphics;; (en plus de #load), vous n'aurez plus besoin de préciser le nom du module, vous pourrez vous contenter de moveto. Soyez cependant prudent(e) : il se peut que deux modules contiennent deux fonctions de même nom (par exemple, Array et List contiennent tous les deux une fonction length). Si c'est le cas, la fonction du premier module auquel vous appliqué open sera écrasée. Pour cette raison, je n'utilise pas open, quitte à en écrire un peu plus.

III) Entrons dans le vif du sujet : comment définir un objet ?
Caml est un langage fonctionnel : cela signifie qu'il est plus porté sur une programmation à base d'objets et de fonctions qu'une programmation à base d'évènements interactifs (comme Javascript ou Basic). Pour définir quelque chose, on commence toujours par l'opérateur let. On donne ensuite le nom de ce qu'on définit (ce nom doit obéir à quelques règles comme ne pas commencer par un chiffre) puis le signe =, la valeur de ce qu'on définit et pour clore la définition, on termine par ;;. Par exemple, la ligne suivante sert à définir un entier que l'on nomme b et qui vaut 5 :
let b = 5;;
L'opérateur let est indispensable pour indiquer que vous faites une définition. Si vous ne le mettez pas, vous réalisez en fait un test d'égalité qui rendra un booléen. Par exemple, tapez maintenant b = 5;; Vous ne définissez rien, vous ne faites que demander si b vaut 5. Caml vous répond true (bah oui).

IV) Comment définir une fonction ?
En fait, pour Caml, une fonction est une valeur comme une autre. Pour définir une fonction, on utilise donc toujours l'opérateur let suivi du nom de l'objet en question ainsi que du signe = qui indique que la définition commence, puis la « valeur » de cette fonction et deux point-virgule qui disent que la définition est terminée.
Vous vous en doutez, la difficulté va être de donner la valeur de cette fonction ! Là aussi, on a une syntaxe spéciale : la valeur d'une fonction s'écrit « fun v -> exp » où v est le nom de la variable et exp est la valeur que devra rendre la foncion pour cette variable v. La flèche s'obtient simplement avec le signe de soustraction suivi du signe de supériorité stricte.
C'est à vous de choisir le nom de la variable et c'est un choix important. En effet, pour Caml, c'est juste un symbole. Vous pouvez donc l'appeler x ou hachis_parmentier, ça ne lui fait rien. En revanche pour vous, le fait de bien nommer vos variables vous permettra quand vous relirez votre programme de voir plus facilement ce qu'elles représentent. Cependant, il vaut mieux éviter l'excès des variables à cent caractères. Bon, juste pour cette fois, pour bien montrer que ça ne change rien, je vais prendre un nom qui n'a rien à voir. Ah oui, je dis ça parce que le temps d'un exemple est venu : je vais créer une fonction, nommée premier_exemple (comme c'est original) et qui à un entier x associe l'entier x+2 : let premier_exemple = fun voiture -> (voiture + 2);;

V) Comment évaluer ?
Définir des fonctions, c'est bien gentil. Mais si on ne peut pas s'en servir pour calculer des valeurs, ça ne sert à rien ! J'ai défini premier_exemple. Comment demander à Caml la valeur de premier_exemple (5) ?
C'est très simple : on recopie le nom de la fonction suivie de la valeur de la variable et des deux points-virgules. On ne met pas de let ni de =, car on ne définit absolument rien, on ne fait que calculer une valeur :
premier_exemple 5;;
Et Caml répond 7 (ouf !). Bien entendu, je peux tout à fait définir un objet en même temps que j'évalue. Supposons que premier_exemple (5) soit pour moi une valeur importante et que je veuille l'appeler nombre. Je peux tout à fait le faire en utilisant cette fois l'opérateur de définition (let). Je définis nombre comme étant la valeur premier_exemple (5) :
let nombre = premier_exemple 5;;
Du coup, chaque fois que je ferai appel à nombre, Caml aura directement sa valeur sans recalculer. Notez que dans cette page, il y avait déjà un exemple d'évaluation. Vous ne trouvez pas ? Regardez deux paragraphes plus tôt : b = 5;; En tapant ça, vous avez demandé à Caml la valeur d'un objet, même si ce n'est pas un nombre mais une valeur booléenne (c'est-à-dire un « nombre logique », vrai ou faux)
Il est temps de parler de dynamisme ou plutôt de dire que Caml n'est pas dynamique. Essayez ça : vous avez défini b comme valant 5. Maintenant, nous alons définir une fonction f qui à x associe x+b (donc qui ajoute 5 à x) : let f = fun x -> x + b;;. On peut vérifier : si vous demandez f 4;;, vous obtenez 9. Maintenant, modifiez la valeur de b : let b = 4;;. Cette action écrase l'ancien objet qui s'appelait b pour en créer un nouveau avec une autre valeur. Réévaluez f 4;;. Vous obtenez à nouveau 9 et non 8 : changer la valeur de b n'a pas changé f, contrairement à ce qui se serait passé pour un « langage dynamique » comme Maple.
Comment expliquer ce phénomène ? Cela vient du fait que Caml évalue directement ce que vous lui donnez : il a évalué votre première valeur de b (5). Puis vous avez défini f et il l'a évaluée. Rappelez-vous : pour lui, une fonction est aussi une valeur ; ainsi quand vous l'avez entrée, il l'a évaluée et définie une bonne fois pour toute comme la fonction qui à x ajoute 5. Après, si vous modifiez la valeur de b, il n'y a pas de raison que cela affecte f.
Caml dispose d'un outil pour créer des fonctions dont le fonctionnement dépendra d'un autre paramètre : les références. Voyez le cours sur les types pour plus d'explication.

VI) Définition locale
Vous pouvez dans un programme utiliser des variables locales. Ce sont des résultats intermédiaires qui ne seront pas rendus et qui ne seront pas conservés quand on aura fini, mais qui servent dans les calculs. Pour les définir, on utilise comme d'habitude l'opérateur let, suivi du nom de la variable, suivi de = et de la définition. Par contre, on ne termine pas par ;; (c'est réservé à une définition globale, non locale) mais par in : on indique que ce qu'on a défini est utilisé dans...
Par exemple, prenons une fonction qui prend un entier n et calcule 2n+1. Bien sûr on pourrait la définir par let affine = fun n -> 2*n + 1;; (Caml connaît la priorité de la multiplication sur l'addition). Mais on peut aussi utiliser une variable intermédiaire m valant 2*n, à laquelle on ajoute 1 pour avoir le résultat :
let affine = fun n -> let m = 2*n in m + 1;;
Et vérifiez : si vous demandez la valeur de m, elle n'existe pas, Caml s'en est servi dans la fonction puis l'a effacée.
Si vous voulez définir plusieurs variables locales simultanément, vous pouvez le faire en utilisant l'opérateur and entre deux définitions. Par exemple, une fonction qui prend un entier n, qui fait le produit de n+1 et n+2 : let produit = fun n -> let m = n + 1 and p = n + 2 in m*p;;
En revanche, vous ne pouvez pas procéder ainsi si la deuxième variable locale dépend de la première. Par exemple, pour un entier n, une fonction calcule la variable locale m valant n + 1, puis la variable p valant m + 1, puis rend 2*p. Si vous tapez let essai = fun n -> let m = n+1 and p = m+1 in 2*p;; vous allez déclencher une erreur. Caml vous dit que la variable m (dans la définition de p) n'est pas définie. Cela vient du fait que m et p sont définis en même temps. Tant que Caml n'est pas arrivé au in, les variables locales ne sont pas définies. Ainsi, lorsque vous définissez p, vous n'avez pas clos la définition de m, Caml ne comprend pas. Pour y remédier, il suffit de terminer la définition de m avec in, puis de refaire une autre définition locale pour p :
let essai_reussi = fun n -> let m = n+1 in let p = m+1 in 2*p;;
Il est possible de nommer une variable locale avec le nom d'une variable globale, ceci ne perturbera pas Caml qui ne modifiera pas abusivement la première variable :
let a = 2;;
let test_variables = fun x -> let a = 2*x in 2*a;;
test_variables 8;;
a;;

Vous avez défini une variable a valant 2. Puis une fonction qui utilise une variable locale a. En appliquant cette fonction à 8, cette variable locale prend la valeur 16. Pourtant si vous évaluez par la suite a, vous avez toujours 2. Vous pouvez donc sans problèmes utiliser des noms de variables globales et de même vous pouvez utiliser dans deux fonctions différentes des variables locales de même nom !

VII) Que signifient les réponses de Caml ?
Il serait peut-être temps de clarifier le sens des réponses de Caml car vous voyez qu'il ne se contente pas de vous donner des valeurs. Quand vous avez tapez premier_exemple 5;;, il a du vous répondre « - : int = 7 ». Que veut dire tout cela ? Analysons dans l'ordre.
Le tiret et les deux points au début indiquent que ce qui commence est une réponse de l'ordinateur sur une évaluation. En gros, on peut les traduire en français par « Vous m'avez demandé d'évaluer la valeur d'un objet et la réponse est : ».
Et la réponse dont il parle se compose de deux choses : son type (ici « int » pour entier) et sa valeur (ici « 7 »), séparés par un signe égal (qu'on traduira en français par « dont la valeur est »). La valeur, vous vous doutez bien de ce que c'est : c'est le résultat de la fonction appelée. Si vous aviez demandé premier_exemple 9, vous auriez eu 11. Mais le type, qu'est-ce donc ?
En mathématiques, on ne peut pas manipuler n'importe quels objets. Vous pouvez multiplier deux nombres entre eux, vous pouvez composer deux fonctions, mais vous n'avez pas le droit d'ajouter un nombre et un vecteur ! Ce n'est pas une règle arbitraire, mais c'est parce que la somme d'un entier et d'un vecteur ne veut absolument rien dire !
C'est la même chose en informatique : les objets qu'on manipule doivent être typés, cela signifie qu'ils doivent appartenir à diverses catégories dans lesquelles ils sont classés. Dans le langage Caml, on trouve entre autres les nombres entiers (int), les nombres réels (float), les tableaux (array), les listes (list), .... Pour plus d'infos, consultez le cours suivant.
Finalement, Caml vous a dit : « Vous m'avez demandé d'évaluer la valeur d'un objet et la réponse est : un entier dont la valeur est 7 ». Vous avez peut-être remarqué que quand vous avez défini un objet, par exemple la valeur nombre égale à premier_exemple(5), la réponse de Caml est légèrement différente. En effet, les réponses avec un tiret correspondent à de simples évaluations. Lors d'une définition (vous créez un objet), le tiret est remplacé par le mot « val » suivi du nom de l'objet, le reste étant identique. Ainsi la réponse pour nombre se lit : « Vous m'avez demandé de définir un objet nommé nombre : c'est un entier dont la valeur est 7 ».
Et pour les fonctions ? C'est pareil ! Regardez le cas de premier_exemple : vous lui avez donné un nom, donc Caml commence comme pour toute définition : « val premier_exemple : » soit en français « vous m'avez demandé de définir un objet nommé premier_exemple : ». Puis vient le type de cet objet : puisque c'est une fonction qui reçoit un entier et rend un entier, son type est « int -> int » (vous retrouvez la flèche utilisée dans la syntaxe des fonctions). Ensuite arrive le traditionnel =. Et enfin la valeur de cette fonction. Sauf que là, si Caml arrivait facilement à vous donner la valeur de nombre, parce que c'est un entier donc il connaît un symbole pour le représenter, Caml ne peut vous donner directement la valeur de la fonction car nous n'avons inventé aucun alphabet permettant de représenter toutes les fonctions qui existent ! Du coup, Caml vous donne « <fun> » comme valeur : il sait parfaitement ce qu'est cette valeur mais ne peut pas vous l'exprimer. La réponse de Caml se lit finalement : « Vous m'avez demandé de définir un objet nommé premier_exemple : c'est une fonction dont l'argument est un entier et le résultat est un entier et dont la valeur est <fun> ».

VIII) Une syntaxe plus simple
Tant qu'on est dans les fonctions, voici une manière plus simple de les définir : on a vu que le code let f = fun x -> x + 5;; indique qu'on définit un élément nommé f, et qu'il s'agit d'une fonction associant à un entier x la valeur x+5. L'utilisation de la structure fun (...) -> n'est pas indispensable. Il existe une autre syntaxe beaucoup plus utilisée car elle paraît plus intuitive. En effet, quand on définit une fonction en mathématiques, on écrit souvent « soit f définie par f(x) = x + 5 ». Caml adopte une syntaxe très proche :
let f x = x + 5;;
On en écrit moins, et le résultat est le même.

IX) Fonctions à plusieurs arguments
C'est bien beau, mais quand on programme, on peut rarement se contenter de fonctions à un argument. Or la programmation en Caml de fonctions à plusieurs variables est très simple. Avec la syntaxe qu'on vient de voir, on se contente simplement de rajouter avant le signe = des autres arguments. Par exemple, définissons une fonction qui ajoute deux entiers :
let ajoute x y = x+y;;
Et il n'y a aucune limite : vous pouvez créer des fonctions avec 58 variables si vous voulez ! Je reviens sur ce que je disais dans le paragraphe IV : quand vous avez plusieurs variables, il est encore plus important de bien choisir leurs noms, sans quoi vous risquez de les mélanger dans les calculs.

X) Ecrivez correctement vos programmes
Voici deux fonctions :
let f x = let a = 2*x in let b = 58 + a and c = 87 + a in let d = 54 - 87 in x + b - (c+d);;

let g x =
   let a = 2*x in
   let b = 58 + a and c = 87 + a in
   let d = 54 - 87 in
x + b - (c+d);;

Voyez-vous une différence ? Ces deux fonctions font en fait la même chose mais la seconde est présentée sous forme « indentée » : cela signifie qu'on y a placé des sauts de ligne et des espaces pour améliorer sa mise en page. En effet, la présence dans un code Caml d'espaces ou de sauts de ligne ne change rien, tant qu'ils ne coupent pas des mots-clés (par exemple, on ne placera pas d'espace au milieu de « let » !). Il est donc recommandé, dès qu'on écrit des fonctions assez longues, d'utiliser cette présentation : elle simplifie grandement la lecture des fonctions, donc si vous devez corriger plus tard votre code, cela sera plus facile.
Une autre chose à faire pour faciliter la correction est d'insérer des commentaires : vous pouvez n'importe où dans votre code (sauf encore au milieu d'un mot) et à volonté insérer des phrases, des mots ou des notes, en veillant simplement à les encadrer par (* et *). Ces commentaires servent surtout à décrire à quoi servent les variables locales ou les actions que vous effectuez. En fait, la présence de (* et *) indique à Caml que ce qui est situé entre les deux est juste là pour les humains et n'a absolument aucun sens pour lui : lors de la compilation, Caml ignorera simplement ces commentaires. Essayez :
let h x =
   let a = 2*x (* bon bah je double x *) in
   let b = 58 + a and c = 87 + a in (* deux variables locales en même temps !!! *)
   let (* là je fais une définition locale *) d = 54 - 87 in
x + b (* oui oui, c'est possible en plein milieu du calcul ! *) - (c+d);; (* fonction terminée ! *)

La fonction a été définie normalement !

Voilà, ce sont les bases de Caml : définition de fonctions et de variables, évaluation, lecture des résultats. Vous n'avez pas compris quelque chose (voir tout) ? Comme je le disais au début, ce n'est absolument pas grave. En voyant des exemples de programmes, vous allez vite comprendre ! C'est beaucoup plus simple qu'en apparence !

> Haut de la page