• Aucun résultat trouvé

Jusqu’`a pr´esent, nous avons ´ecrit de petits programmes dans un sous-ensemble de Caml : la partie d´eclarative, la plus proche des math´ematiques. Nous avons toujours d´efini des fonctions qui retournaient le r´esultat que nous voulions calculer. Ces fonc- tions calculent le r´esultat souhait´e au sens des calculs math´ematiques, c’est-`a-dire par simplifications successives d’une expression. Ce style de programmation `a l’aide de fonctions s’appelle la programmation fonctionnelle.

Une autre fa¸con de calculer consiste `a consid´erer qu’un calcul est un processus ´evolutif, o`u le temps a son importance. Il s’agit de modifier un ´etat : l’ordinateur com- mence l’ex´ecution du programme dans un certain ´etat initial, que l’ex´ecution du pro- gramme modifie jusqu’`a parvenir `a un ´etat final qui contient le r´esultat voulu. On change l’´etat courant par modification du contenu de la m´emoire de l’ordinateur (`a l’aide d’affectations), ou encore par interaction avec le monde ext´erieur : interrogation de l’utilisateur, affichage de r´esultats, lecture ou ´ecriture de fichiers, bref tout ce qu’on nomme les entr´ees-sorties. Toutes ces op´erations qui modifient physiquement le contenu des adresses m´emoire sont appel´ees effets (ou encore effets de bord) :

Un effet est une modification d’une case de la m´emoire (tableau ou r´ef´erence), ou encore une interaction avec le monde ext´erieur (impression ou lecture).

Ce style de programmation par effets s’appelle la programmation imp´erative. Ce nom provient ´evidemment de la signification du mode imp´eratif dans la conjugaison des verbes. En effet, les programmes imp´eratifs d´ecrivent explicitement `a la machine la suite des op´erations `a effectuer (fais ci, fais ¸ca). Au contraire, en programmation fonc- tionnelle, on laisse la machine calculer le r´esultat comme elle le peut `a partir d’une for- mule, sans lui pr´eciser compl`etement l’ordre dans lequel elle doit op´erer. Par exemple, pour calculer le carr´e d’un nombre x, on ´ecrit x * x en programmation fonctionnelle. Au contraire, une m´ethode imp´erative serait de r´eserver une case m´emoire comme ac- cumulateur, de l’initialiser avec x, puis de remplacer le contenu de cet accumulateur par son contenu multipli´e par lui-mˆeme. Le r´esultat cherch´e serait maintenant dans l’accumulateur. Dans un cas si simple, ces descriptions sont ´evidemment caricaturales, mais l’id´ee est la bonne.

Le style imp´eratif implique la modification de l’´etat de la m´emoire, donc l’utilisation de structures de donn´ees modifiables (par exemple les tableaux dont les ´el´ements peu- vent ˆetre chang´es dynamiquement) et l’emploi de commandes. Les commandes sont des expressions qui ne retournent pas de valeurs int´eressantes ; leur r´esultat est simplement une modification de l’´etat courant, c’est-`a-dire un effet. Lorsqu’une fonction se contente d’ex´ecuter une s´erie de commandes, on l’appelle souvent proc´edure. Une proc´edure en Caml est donc simplement une fonction qui se contente de faire des effets, sans produire de r´esultat au sens math´ematique.

Nous aurions pu nous cantonner au sous-ensemble fonctionnel de Caml et cependant ´ecrire de tr`es jolis programmes. Mais c’eˆut ´et´e donner une fausse image de Caml : ce qui fait la puissance du langage c’est justement qu’il ne se limite pas `a la programmation fonctionnelle, mais int`egre harmonieusement programmation fonctionnelle et program- mation imp´erative. De plus, nous cherchons avant tout `a vous montrer les programmes les plus simples et les plus clairs possibles : nous avons donc besoin de tous les outils que Caml met `a notre disposition.

De surcroˆıt, la programmation imp´erative n’est pas seulement indispensable pour traiter les probl`emes d’interaction avec le monde ext´erieur (entr´ees-sorties). Dans cer- tains cas un algorithme, c’est-`a-dire une m´ethode de r´esolution d’un probl`eme, exige moins de calculs lorsqu’il est ´ecrit en style imp´eratif que lorsqu’il est ´ecrit en style fonc- tionnel. Enfin, certains algorithmes s’expriment naturellement en termes d’´evolution d’un ´etat ; la programmation imp´erative s’impose alors.

Nous avons pour l’instant illustr´e les effets d’entr´ees-sorties, plus pr´ecis´ement les impressions. Nous allons maintenant faire des effets sur la m´emoire, ce qu’on appelle aussi des modifications physiques ou modifications en place de donn´ees. Pour cela il nous faut disposer de cases m´emoire modifiables par le programme. Caml propose pour cela les notions de r´ef´erences et de tableaux. Nous commen¸cons par ´etudier les tableaux, qui sont plus simples.

Puisque la notion de temps intervient en programmation imp´erative, il nous faut un moyen de sp´ecifier au langage « fait ceci d’abord » et « fait cela ensuite » : c’est la notion de s´equence que nous avons d´ej`a vue au chapitre 1. Nous avons ´egalement besoin de r´ep´eter des suites d’effets : c’est la notion de boucles. Nous d´ecrivons ces construction, puis appliquons ces outils au calcul sur les polynˆomes.

Boucles 39

3.2

Boucles

Caml fournit deux sortes de boucles pour r´ep´eter des effets : la boucle « pour » et la boucle « tant que ». La boucle « pour » r´ep`ete un calcul un nombre de fois fix´e `a l’avance ; la boucle « tant que » r´ep`ete un calcul tant qu’une condition reste vraie.

Boucle «tant que»

Boucle « tant que » ::= while expression (while : tant que) do expression done (do : faire, done : fait)

La signification de while condition do actions done est simplement de faire les actions tant que la condition est vraie. La condition est test´ee au d´ebut de chaque it´eration. Si elle est initialement fausse, les actions ne sont jamais ex´ecut´ees. Dans certains cas, la boucle « tant que » sert `a r´ep´eter ind´efiniment les mˆemes actions jusqu’`a un ´ev´enement exceptionnel. Dans ce cas, la condition de boucle est tout simplement le bool´een true, comme dans while true do actions done.

Boucle «pour»

Boucle « pour » ::= for ident = expression (for : pour)

(to | downto) expression (to : jusqu’`a, down : en bas) do expression done (do : faire, done : fait)

La s´emantique, c’est-`a-dire la signification, de l’expression for i = d´ebut to fin do actions doneest de faire les actions avec i = d´ebut, puis avec i = d´ebut + 1 et ainsi de suite, jusqu’`a i = fin. En particulier, si d´ebut > fin, on n’´evalue jamais actions. Pour la version downto, on d´ecr´emente l’indice de boucle i (on lui soustrait 1) `a chaque tour, au lieu de l’incr´ementer (lui ajouter 1). L’indice de boucle est forc´ement du type entier. Le nom associ´e `a l’indice de boucle est introduit par la boucle (comme par une liaison let) ; sa liaison n’est valide que pendant le corps de la boucle. Prenons un exemple simple : nous imprimons les dix chiffres `a l’aide d’une boucle de 0 `a 9. Nous d´efinissons une proc´edure imprime_chiffre dont l’argument est « rien », et nous la d´eclenchons en l’appliquant `a « rien ». # let imprime_chiffres () = for i = 0 to 9 do print_int i done; print_newline ();;

imprime_chiffres : unit -> unit = <fun> # imprime_chiffres ();;

0123456789 - : unit = ()