Home

Le Langage Caml

image

Contents

1. unit 176 Syntaxe abstraite syntaxe concr te logo ve spirale logo ve spirale O 179 5 0 5 360 O 178 5 0 5 360 unit unit Cette fonction est tonnamment sensible la valeur de ses param tres de d part Les deux dessins ci dessus correspondent une variation d un degr de l angle toutes choses restant gales par ailleurs De m me voyez la diff rence entre les deux dessins suivants o l angle de d part n a t modifi que de 0 3 degr s logo ve spirale logo ve spirale 0 79 8 0 4 360 0 79 5 0 4 360 unit unit NY EE N f o Z Nous crivons maintenant une proc dure analogue mais qui incr mente l angle de vis e au lieu de la distance de d placement logo pour spirala d a i n si n gt 0 av d td a spirala d a i i Cn 1 stop l unit On obtient encore une fois des figures tr s diverses Ajout des proc dures 177 logo ve spirala logo ve spirala 5 0 89 5 1440 4 0 5 181 5 1500 unit unit Au fait spirale et spirala sont des proc dures r cursives Mais qu avons nous fait pour que les proc dures de notre mini Logo puissent tre r cursives Comment se fait il que nous soyons capables de les ex cuter Nous avons vu qu en Caml cela n allait pas de soi puisqu il nous avait fallu pour cela utiliser le
2. formule n i 0 La notation X 0 formule i se lit somme de gale 0 n de formule i Par exemple si la formule est r duite on obtient la somme des nombres de 0 n n Xis O0 1 n i 0 De m me si la formule est i la somme correspondante est celle des carr s des nombres entre Qet n n YP PHPH oH n i 0 On exprime ainsi de mani re tr s concise deux polyn mes g n raux P et Q et leur somme P Q m n max m n Si P X piri et Q Sat alors P Q 5 pi qi z i 0 i 0 i 0 La traduction en Caml de cette d finition est tr s simple on cr e d abord un tableau somme pour contenir la somme des deux polyn mes P et Q Ce tableau a pour longueur le maximum des longueurs de P et Q qu on calcule avec la fonction pr d finie max Il suffit de recopier les coefficients de l un des polyn mes dans les cases du r sultat puis d y ajouter les coefficients de l autre let ajoute_polyn mes_pleins p q let somme make_vect max vect_length p vect_length q O in for i 0 to vect_length p 1 do somme i lt p i done for i 0 to vect_length q 1 do somme i lt somme i q i done somme ajoute_polyn mes_pleins int vect gt int vect gt int vect lt fun gt Comme promis nous pouvons maintenant calculer la valeur de 2x 2x imprime_ polyn me _ plein ajoute_polyn mes_pleins 0 21 CIO 21 0 4x unit et v rifier un de nos calculs p
3. string Cam let sous_cha ne s d part fin sub_string s d part fin d part 1 sous_cha ne string gt int gt int gt string lt fun gt Suppression des accents La simplification d un mot consiste supprimer les accents que l on consid re comme non significatifs On admet galement que l utilisateur ait pu taper e pour ou e pour Enfin on supprime les articles lid s qui apparaissent ventuellement au d but du mot Par exemple l air devient air Plut t que de mettre en dur ces conventions dans le code de la fonction de simplification nous crivons une fonction g n rale param tr e par une table de sim plifications qui n est autre qu une liste d association entre cha nes let simplifications a etes e e e u ao Man e e e e teni e ut Mu qu LUS QU AUS JA EU d DIS N E La fonction de simplification consiste recopier le mot argument dans une nouvelle cha ne Les caract res sont recopi s un par un sauf si le caract re courant et les car act res suivants forment une des cha nes simplifier auquel cas on les remplace par la cha ne associ e dans la table de simplifications let simplifie _ mot mot let nouveau_mot create_string string_length mot in let i ref O and j ref O in let rec cherche_ traduction function gt raise Pas_trouv
4. Il nous faut faire ici une remarque importante que nous utiliserons quelques fois Il s agit d un exemple de r gle de calcul sur les programmes qui permet l occasion de simplifier les programmes Ce genre de r gles constitue l quivalent informatique des r gles de simplification des math matiques Cette r gle est tr s facile elle stipule qu il est inutile de d finir une fonction qui se contente d en appeler imm diatement une autre let successeur x x 1 successeur int gt int lt fun gt let succ function x gt successeur x succ int gt int lt fun gt La fonction succ applique imm diatement la fonction successeur son argument x elle retournera donc forc ment toujours les m mes valeurs que la fonction successeur c est la m me fonction que successeur On dit que la fonction succ est gale la fonction successeur D ailleurs on aurait tr s bien pu la d finir par let succ successeur succ int gt int lt fun gt Plus g n ralement on a Pour toute fonction f function x gt fx est quivalent f De la m me fa on qu en math matiques les r gles du calcul alg brique permettent de remplacer x x par 0 nous utiliserons la r gle pr c dente pour crire successeur au lieu du programme function x gt successeur x Nous aurons ainsi simplifi notre programme en utilisant une r gle universelle sans m me avoir besoin de r fl chir
5. Cette criture est extr mement compacte on peut m me la consid rer comme l gante Cependant l emploi des it rateurs en produisant un code compact a tendance cacher la complexit des algorithmes Nous allons voir que notre fonction implose a une com plexit lev e quadratique en le nombre de cha nes concat n es cause de la cr ation de nombreuses cha nes interm diaires 100 Listes L op rateur de concat nation de cha nes Pour calculer la complexit de la fonction implose il nous faut r fl chir sur le fonc tionnement de l op rateur de concat nation de cha nes tant donn es deux cha nes de caract res c et c2 en arguments alloue une nouvelle cha ne de caract res pour y loger la concat nation des deux cha nes puis y recopie c et c2 correctement d cal es 2 0 0 0 0 0 0 0 8 09 8 8 8 80 010 010 0 0 0 0 0 C1 Nous crivons l op rateur sous la forme d une fonction pr fixe concat let concat ci c2 let r sultat create_string string_length ci string_length c2 in blit_string ci 0 r sultat 0 string_length c1 blit_string c2 0 r sultat string_length c1 string_length c2 r sultat concat string gt string gt string lt fun gt On rappelle que l appel de la proc dure blit_string source indice_source destination indice_destinatio
6. La compilation de la fonctionnalit Les fermetures Au niveau du compilateur proprement dit la principale nouveaut de Caml par rapport Pascal est la pleine fonctionnalit Lorsque les fonctions peuvent tre calcul es et renvoy es en r sultat il n est plus possible de les repr senter unique ment par des adresses de morceaux de code machine Comme nous l avons vu dans l interpr teur mini Caml il faut introduire la notion de fermeture c est dire trans former les fonctions en structures de donn es allou es contenant en plus de l adresse du code de la fonction l environnement au moment de la d finition de la fonction Le code produit pour une d finition de fonction alloue cette fermeture et y stocke l environnement courant Le code produit pour appliquer une fonction va chercher dans la fermeture l adresse du code de la fonction et se branche cette adresse non sans avoir pass la partie environnement de la fermeture en argument suppl mentaire la fonc tion Le corps de la fonction est compil de mani re aller chercher dans cet argument suppl mentaire la valeur des identificateurs libres Appel de fonctions inconnues En plus du recours aux fermetures la pleine fonc tionnalit impose un m canisme uniforme d appel de fonctions Toute fonction Caml est susceptible d tre appel e par une fonction qui ne conna t rien de la fonction qu elle appelle par exemple map re oit n importe quell
7. Plein of int vect Creux of mon me list Le type poly est d fini L avantage de cette d finition est d avoir explicitement nomm les caract ristiques d un mon me Par exemple la fonction plein_vers_creux deviendrait let plein_vers_creux v let 1 ref in for i vect_length v 1 downto 0 do 1 degr i coefficient v i 1 done Iss plein_vers_creux int vect gt mon me list lt fun gt On a donc remplac la paire v i i par enregistrement degr i coefficient v i dans le code de l ancienne fonction La diff rence est faible mais elle suffit rendre le code plus facile lire et crire D ailleurs la premi re version de plein_vers_creux crite au cours de la r daction de ce livre tait fausse au lieu de v i i nous avions crit i v i parce que nous avions oubli dans quel ordre nous avions d cid de mettre le degr et le coefficient dans les couples d entiers mod lisant les mon mes Cela ne se voyait pas sur le type des polyn mes creux la convention tant simplement r partie dans le code des fonctions de manipulation des polyn mes creux Cette erreur ind tectable par typage est facilement vit e quand on crit explicitement les noms degr et coefficient et que c est le compilateur qui r tablit l ordre des rubriques 6 6 Structures de donn es mutables Nous connaissons d j certaines structures de donn es dont le contenu est
8. camlc c demo ml compile demo ml HHEH HHH Exemples de th or mes 223 camlc o demo prop zo do_list load_object prop zo lexuniv zo asynt zo demo zo lexuniv zo asynt zo demo zo Le d monstrateur se lance par l incantation suivante camlrun demo demo__boucle Nous pouvons alors taper des propositions en r ponse au signe d invite gt gt gt Pour sortir du programme il faut taper un caract re fin de fichier ctr1 D en Unix ou une interruption ctr1 C en Unix 12 7 Exemples de th or mes Simples mais tellement vrais Pour montrer les capacit s de notre programme nous tablissons des th or mes simples mais de moins en moins intuitifs Tout d abord le contraire du contraire d une proposition c est la proposition elle m me gt gt gt non non P lt gt P Th or me pour toute proposition P non non P lt gt P Le tiers exclus une proposition est toujours soit vraie soit fausse mais jamais les deux en m me temps gt gt gt P ou non P lt gt vrai Th or me pour toute proposition P P ou non P lt gt vrai gt gt gt P et non P lt gt faux Th or me pour toute proposition P P et non P lt gt faux Dire qu une proposition est quivalente vrai c est simplement dire que la propo sition est vraie inversement dire qu elle est quivalente faux c est dire que sa n gation est vraie gt gt gt
9. compte_hanoi 16 int 7 int 1023 int 65535 On devine la propri t suivante pour tout n compte_hanoi n 2 1 Nous allons la d montrer en utilisant le principe de r currence Nous d finissons donc formellement 34 R cursivit la propri t P par P n est vraie si et seulement si compte_hano i n 2 1 La proposition P 0 est vraie car compte_hanoi 0 0 et 2 1 1 1 0 Supposons P n vraie et montrons qu alors P n 1 est vraie Pour montrer P n 1 il faut d montrer compte_hanoi n 1 2 1 Or d apr s la d finition de la fonction compte_hanoi on a compte_hanoi n 1 2 x compte_hanoi n 1 1 1 soit compte_hanoi n 1 2 x compte_hanoi n 1 Mais par hypoth se de r currence P n est vraie donc compte_hanoi n 2 1 En reportant dans l galit pr c dente on obtient compte_hanoi n 1 2 x 2 1 1 Mais 2 x 2 1 1 2 1 2 1 2 1 1 donc compte_hanoi n 1 2 1 et P n 1 est vraie Il s ensuit d apr s le principe de r currence que P n est vraie pour tout n Avec ce nouveau r sultat nous sommes autoris s red finir compte_hanoi comme la fonction qui n associe 2 1 Pour avoir une id e du nombre de mouvements n cessaires pour r soudre le probl me avec 64 disques nous sommes oblig s de faire les calculs en virgule flottante car le r sultat exc de d
10. failwith string gt a lt fun gt Si les exceptions pr d finies ne vous satisfont pas parce que vous souhaitez par exemple que votre valeur exceptionnelle transporte autre chose qu une cha ne de car act res vous pouvez d finir une nouvelle exception En effet le type exn est un type somme il y a plusieurs exceptions diff rentes c est donc un type ou mais d un genre tr s particulier sa d finition n est jamais achev e C est pourquoi il est possible tout moment de lui ajouter de nouveaux constructeurs soit constants soit fonction nels Pour d finir un nouveau constructeur du type exn donc une nouvelle exception on utilise le mot cl exception suivi d une d finition de constructeur de type somme Pour d finir la nouvelle exception constante Stop on crira donc simplement Les exceptions 129 exception Stop L exception Stop est d finie La d finition d une exception fonctionnelle comportera une partie of type qui pr cise le type de l argument de l exception exception Erreur_fatale of string L exception Erreur_fatale est d finie raise Erreur_fatale Cas impr vu dans le compilateur Exception non rattrap e Erreur_fatale Cas impr vu dans le compilateur Voici la description pr cise des d finitions d exception l aide de diagrammes syntax iques D finition d exceptions exception d finition de constructeur and d finition de constr
11. gt Integer Integer not gt Boolean Boolean and type_op_binaire function x 2 gt Integer Integer Integer s lt gt lt gt lt gt gt Integer Integer Boolean and or gt Boolean Boolean Boolean Typage des instructions L tape suivante consiste typer les instructions Au contraire de type_expr la fonction type_instr ne renvoie rien il n y a pas de type calculer seulement des types v rifier Typage 287 Fichier typage ml let rec type_instr env function Affectation _var nom_ var expr gt let type_var cherche_variable nom_var env in v rifie _non_ tableau affectation de nom_ var type_var v rifie type la variable nom_var type_var type_expr env expr Affectation _tableau expri expr2 expr3 gt let type_ l ments v rifie tableau type_expr env expri in v rifie_non_ tableau affectation de tableau type_ l ments v rifie_type l indice de tableau Integer type_expr env expr2 v rifie_type affectation de tableau type_ l ments type_expr env expr3 Appel nom_proc args gt let proc cherche_proc dure nom_proc env in type_application env nom_proc proc proc_param tres args If condition branche_oui branche_non gt v rifie_type la condition de IF Boolean type_expr env condition type_instr env branche_oui type_instr env branche _non While condition corps gt v
12. int list 3 2 1 Notre algorithme est maintenant lin aire Cette m thode d accumulation des r sultats interm diaires dans un argument suppl mentaire de la fonction est souvent une bonne piste suivre pour optimiser une fonction quand cette fonction pose des probl mes d efficacit Encore faut il prouver que la fonction sujette optimisation est r ellement le goulet d tranglement du programme puis d montrer par une tude de complexit que l optimisation va vraiment am liorer les performances C est videmment tr s dif ficile En r gle g n rale on se contentera d crire des programmes corrects et lisibles 5 11 Listes et r currence Nous montrons dans cette section comment prouver des propri t s sur les listes Bien qu un peu th orique ce n est pas tr s complexe puisqu il s agit d une extension simple du principe de r currence 104 Listes Lorsque nous avons crit des fonctions r cursives sur les entiers nous apportions la preuve de leurs propri t s en utilisant le principe de r currence Mais ce principe ne s applique plus dans le cas des listes puisqu il concerne uniquement les propri t s d finies sur les nombres entiers Comment prouver des propri t s des listes Il suffit de se ramener au cas des entiers en raisonnant sur le nombre entier qui mesure la longueur de la liste Le principe de r currence nous permet alors de d montrer qu une propri t est vraie pour des li
13. quivalence de leur n gation gt gt gt non P lt gt non Q lt gt P lt gt Q Th or me pour toutes propositions Q P non P lt gt non Q lt gt P lt gt Q Mais on conna t souvent moins bien la notion de proposition contrapos e d une im plication La contrapos e de P Q est la proposition non Q non P Elle est int ressante car elle est quivalente la proposition de d part Cependant il est quelquefois plus facile de prouver la contrapos e d une proposition que la proposition elle m me Nous tablissons le th or me gt gt gt P gt Q lt gt non Q gt non P Th or me pour toutes propositions Q P P gt Q lt gt non Q gt non P La d monstration par l absurde consiste pour d montrer P Q supposer vraie l hypoth se P et fausse la conclusion Q et en d duire une contradiction ce qui revient dire qu on en d duit la proposition faux La validit de cette m thode de d monstration repose donc sur le th or me suivant gt gt gt P et non Q gt faux lt gt P gt Q Th or me pour toutes propositions Q P P et non Q gt faux lt gt P gt Q La r ponse aux questions de l introduction Nous r pondons maintenant aux interrogations du d but de ce chapitre Nous avions pos la question sachant que la phrase P est vraie et que la phrase Q est fausse est ce que la phrase obtenue en disant P et Q est une
14. La fonction ajoute est un peu plus compliqu e il faut parcourir la liste jusqu trouver un l ment de priorit plus grande que l l ment ins rer Fichier fileprio ml let rec ajoute file prio elt match file with O gt prio elt prioi elti reste gt if prio lt priol then prio elt reste else priol elt1 ajoute reste prio elt Avec cette impl mentation des files d attente lop ration extraire est en temps con stant mais l op ration ajoute est en temps n 2 en moyenne et n dans le pire des cas o n est le nombre d l ments de la file d attente Dans l algorithme de Huffman on 248 Compression de fichiers ins re jusqu 256 l ments dans des files de 0 255 l ments ce qui donne au pire peu pr s 32000 tours dans la fonction ajoute Il est craindre que cette impl mentation na ve ne soit pas assez efficace Voici une seconde impl mentation du module fileprio o les files sont repr sent es par des arbres tournoi aussi appel s heaps tas dans la litt rature en anglais Fichier fileprio ml type a t Vide File of int a x a t at let vide Vide Les feuilles de l arbre constructeur Vide ne portent pas d information Les n uds de l arbre constructeur File portent chacun un l ment de la file avec sa priorit plus deux sous arbres traditionnellement appel s le fils gauche et le fi
15. Le bonheur existe aussi vous savez Comment vous tes vous connus malheur malheurs Comment cela se passe t il avec vos amis l Malheur est peut tre exag r non Avez vous de fr quentes disputes avec vos Le malheur est une notion relative amis Cam lia 139 Des amies Faudrait savoir est ce ML ou pas Des petites amies langage langages Des petits amis l Vous voulez dire langage de Depuis combien de temps vous programmation connaissez vous Je ne connais que le langage Caml deteste hais Connaissez vous bien le langage Caml l Est ce raisonnable de d tester ce Hors de Caml point de salut non point A mon avis Caml est sans gal Le mot n est il pas un peu fort Oui c est puissant mais quelle syntaxel Mod rez un peu vos sentiments l Et les probl mes de syntaxe l mari 1 l tes vous depuis longtemps ensemble Comment l avez vous rencontr programme programmes Pensez vous qu il faille tre fid le son l Vous parlez de programmes d ordinateur mari Il y a souvent des erreurs dans vos C amour programmes non I Et l amour fou qu en pensez vous Connaissez vous vraiment la C est compliqu l amour non programmation L amour l amour le connaissez vous Vos programmes s criraient plus vraiment naturellement en Caml
16. f gy n est pas quivalent fgy 1 8 Diagrammes syntaxiques Nous r sumons la mani re d crire les constructions de Caml au moyen de d finitions simplifi es de syntaxe telles que expression entier cha ne de caract res bool en Cette d finition signifie qu une expression du langage Caml expression est ou bien un entier entier ou bien une cha ne de caract res cha ne de caract res ou bien un bool en bool en ou bien Ceci n est qu un exemple et nous ne faisons videmment pas figurer toutes les constructions concernant les expressions D ailleurs nous savons d j qu une s quence est une expression elle devrait donc figurer dans l ensemble des expressions de m me que les expressions parenth s es toute expression entour e de parenth ses est une expression Avec ce formalisme une s quence se d crit par s quence expression expression ou encore si elle est d limit e par les mots cl s begin et end s quence begin expression expression end Cette m thode de description de la syntaxe d un langage est appel e syntaxe BNF pour Backus Naur Form des noms de John Backus et Peter Naur qui l ont r pandue 2 R cursivit O l on apprend parler de ce qu on ne conna t pas encore OUS NE CONNAISSEZ PAS les fonctions r cursives ou n y avez jamais rien compris ou bien vous vous passionnez pour les tours de Hano Alo
17. int let f x 1 f a gt int lt fun gt Les types polymorphes sont donc utilis s pour r sumer toutes les solutions possibles un syst me d quations entre types qui n a pas assez de contraintes pour tre r solu compl tement par des types de base Les variables de types qui deviennent ainsi des param tres du sch ma de type sont celles qui ne re oivent jamais de valeur et qui ne sont donc soumises aucune contrainte dans le programme M thode de r solution Pour r soudre les syst mes d quations entre types on utilise en premi re approx imation le m canisme classique de remplacement des inconnues dont on conna t d j la valeur C est ce que nous venons de faire dans l exemple pr c dent en rempla ant t par la valeur connue int En fait le m canisme de r solution est plus g n ral c est une m thode de propagation de contraintes d galit connue sous le nom de m canisme d unification Nous le verrons en d tail par la suite Principes de la synth se de types 341 Pour mod liser les syst mes d quations nous aurons donc besoin de variables de type pour les inconnues du syst me de types constants pour les constantes du syst me et d op rations entre types comme la fl che gt ou le produit Nous aurons galement besoin de mod liser les quations elles m mes le signe pourrait on dire et donc de rendre compte du remplacement d une variable par sa valeur Ce remplacement sera
18. let pelle_envers s pelle_envers_aux s string_length s 1 pelle_envers string gt unit lt fun gt Fonctions r cursives simples 25 pelle_envers snob bons unit La seconde pelle l endroit en commen ant par le premier caract re et en s appelant r cursivement sur le prochain caract re let rec pelle_aux s i if i lt string_length s then begin print_char s i print _char pelle_aux s i 1 end pelle_aux string gt int gt unit lt fun gt let pelle s pelle_aux s 0 pelle string gt unit lt fun gt pelle snob sn ob unit Ces deux exemples utilisent une forme nouvelle de l alternative la construction if then sans partie else La partie else omise est implicitement compl t e par le compilateur qui ajoute else autrement dit sinon rien Ainsi le code if i gt 0 then begin end est compris par Caml comme si nous avions crit if i gt 0 then begin end else Cette compl tion automatique vous explique pourquoi la phrase suivante est mal typ e if true then 1 Entr e interactive gt if true then 1 S a Cette expression est de type int mais est utilis e avec le type unit Retenons la d finition d une alternative sans partie else if cond thene est quivalent if cond then e else Les palindromes Un palindrome est un mot ou un groupe de mots sans blanc
19. let rec f O in Maintenant nous d finissons facilement la fonction factorielle let rec factorielle n if n 0 then 1 else n factorielle n 1 factorielle int gt int lt fun gt factorielle 3 int 6 Compter l endroit et l envers Pour comprendre comment s ex cute un appel une fonction r cursive d finissons une fonction qui num re les nombres par ordre d croissant jusqu 1 partir d une certaine limite par exemple pour une limite de 5 nous voulons obtenir l impression de 5432 1 sur l cran Bien que le but de ce programme soit exclusivement de produire des effets la r cursivit s y introduit naturellement puisque num rer partir d une certaine limite n c est si la limite est 0 alors ne rien faire sinon imprimer n puis num rer les nombres pr c dents Si l on se rend compte que num rer les nombres pr c dents consiste tout simplement appeler notre fonction avec la nouvelle limite n 1 on obtient le programme suivant let rec compte_ _ rebours n if n 0 then else begin print_int n print_string compte_ _rebours n 1 end compte_ _rebours int gt unit lt fun gt mn compte_ _rebours 10 100987654321 unit La fonction d impression des entiers au terminal se nomme tout naturellement print_int par analogie avec la fonction d impression des cha nes print_string Vous devinez l
20. lt MC array MC Entier bas MC Entier haut MC MC of lire_type ty gt gt Array bas haut ty let rec lire_variables function lt MC var Ident nom MC lire_type ty MC lire_variables reste gt gt nom ty reste k gt gt let lire_un_param tre function lt Ident nom MC lire_type ty gt gt nom ty let lire_param tres function lt MC R lire_liste lire_un_param tre param tres Typage 283 MC gt gt param tres let lire_proc dure function lt MC procedure Ident nom lire param tres p MC lire_variables v lire_instr i MC gt gt nom proc_param tres p proc_variables v proc_corps i Le let lire_fonction function lt MC function Ident nom lire param tres p MC lire_type ty MC lire_variables v lire_instr i MC gt gt nom fonc _param tres p fonc _type_r sultat ty fonc_variables v fonc_corps i let rec lire_proc_fonc function lt lire_proc dure proc lire_proc_fonc procs foncs gt gt proc procs foncs lt lire_fonction fonc lire_proc_fonc procs foncs gt gt procs fonc foncs lt gt gt 0 let lire_prog function lt MC program Ident nom_du_programme MC lire_variables v lire_proc_fonc p f lire_instr i gt gt prog_variabl
21. lt Mot stop gt gt Stop lt Mot si expression el Symbole gt Symbole liste_d ordres alors liste_d ordres sinon gt gt Si ei e2 alors sinon lt Mot r p te Mot rep expression e liste_d ordres 1 gt gt Rep e 1 lt Mot f liste d expressions exprs gt gt Ex cute f exprs expression e2 liste_d ordres function lt Symbole suite_d ordres l Symbole gt gt 1 suite_d ordres function lt ordre ord suite_d ordres 1 gt gt ord 1 lt gt gt nombre function lt Symbole nombre n gt gt begin match n with Entier i gt Entier i Flottant f gt Flottant f end lt Constante_enti re i gt gt Entier i lt Constante_flottante f gt gt Flottant f expression_simple function lt nombre n gt gt Constante n lt Symbole Mot var gt gt Variable var lt Symbole expression e Symbole gt gt e expression function lt expression_simple e reste_de_l expression e e gt gt e Ajout des proc dures 175 and reste_de_l expression e function lt Symbole expression e2 gt gt Somme e e2 lt Symbole expression e2 gt gt Produit e e2 lt Symbole expression e2 gt gt Diff rence e e2 lt Symbole
22. map fib 1 2 8 4 5 6 1 2 8 5 8 13 1 334 Ex cution d un langage fonctionnel 17 5 Pour aller plus loin Les modes d valuation Vous aurez sans doute remarqu que notre valuateur calcule les arguments d une fonction avant de l appeler Cela para t naturel mais en fait ce travail s av re inutile dans le cas o la fonction n utilise pas son argument Pire il peut se produire que le calcul de l argument ne termine pas alors m me qu il n est pas utilis pour obtenir le r sultat final Il arrive donc que notre valuateur ne parvienne pas calculer un r sultat pourtant raisonnable La m thode suivie par notre valuateur est appel e l appel par valeur puisqu on appelle les fonctions apr s avoir calcul la valeur de tous leurs ar guments La strat gie qui consiste attendre que le besoin de calculer l argument se fasse express ment sentir dans le corps de la fonction s appelle l appel par nom Son inconv nient majeur est qu un m me argument est calcul plusieurs fois s il est utilis plusieurs fois dans le corps de la fonction C est pourquoi il existe un troisi me mode d appel des fonctions l appel par n cessit qui consiste comme dans l appel par nom attendre que la valeur d argument soit absolument n cessaire avant de le calculer mais mettre en m moire cette valeur calcul e pour la r utiliser telle quelle chaque fois qu on en a besoin De
23. original traduction reste gt let longueur string_length original in if i longueur lt string_length mot amp amp sub_string mot i longueur original then longueur traduction else cherche_traduction reste in while i lt string_length mot do try let longueur traduction cherche_traduction simplifications in blit_string traduction 0 nouveau_mot j string_length traduction i i longueur Cam lia 135 j j string_length traduction with Pas_trouv gt nouveau_mot j lt mot l il i i li 1 Joos kj 1 done sub_string nouveau_mot 0 j simplifie_mot string gt string lt fun gt Division en mots La division d une cha ne de caract res en mots est une autre op ration d licate Elle consiste parcourir la cha ne l envers la recherche des s parateurs D s qu un s parateur est trouv on extrait un mot qu on ajoute la liste de mots mots On maintient un compteur j qui indique le dernier caract re du mot courant tandis que le compteur de boucle i sert en rep rer le d but Notez que le caract re fin de ligne est crit n l int rieur d une cha ne de caract res la notation n repr sente aussi un retour la ligne let divise_en_mots cha ne let mots ref in let j ref string_length cha ne 1 in let ajoute_mot i j if i lt j then mots simplifie mot sous_cha ne cha ne i j mots in for i string_leng
24. reconna tre de l tat de d part vers l tat d arriv e Par exemple dans l automate ci dessus on peut passer de l tat de gauche l tat de droite si la cha ne reconna tre commence par ab ac b ou c Dans un automate certains tats sont marqu s comme tats terminaux Un des tats est marqu comme tat initial Dans les dessins l tat initial est signal par une petite fl che entrante du c t gauche les tats terminaux sont en trait plus pais OOt Le jeu consiste essayer de trouver un chemin qui part de l tat initial et aboutit sur un tat terminal apr s avoir lu tous les caract res de la cha ne donn e en entr e Si un tel chemin existe on dit que l automate reconna t la cha ne Par exemple l automate ci dessus gauche reconna t les mots le la les et rien d autre L automate ci dessus droite reconna t les nombres crits en base deux c est dire les m mes mots que l expression rationnelle 01 16 4 Des expressions rationnelles aux automates Expressions rationnelles et automates sont reli s de mani re tr s troite toute expression rationnelle correspond un automate qui reconna t exactement les m mes mots que l expression de d part Les automates peuvent donc tre vus comme des formes compil es d expressions rationnelles Nous allons maintenant programmer une fonction qui transforme une expression rationnelle en automate
25. 0 then x else x valeur_absolue int gt int lt fun gt valeur_absolue 3 int 3 valeur_absolue 3 int 3 Valeurs et programmes 13 Valeurs de v rit Remarquons que les tests calculent un r sultat une valeur de v rit Une valeur de v rit est soit vrai soit faux ce qui se note true et false en Caml On appelle aussi les valeurs de v rit valeurs bool ennes en l honneur du logicien Boole elles sont du type bool On peut donc employer les tests pour calculer un bool en 2 lt i bool false valeur_absolue 3 valeur_absolue 3 bool true 1 5 Valeurs et programmes Nous venons de faire des calculs Mais o sont donc les programmes Ce sont tout simplement les fonctions Un programme consiste en une d finition de fonction qui calcule le r sultat d sir En g n ral cette fonction utilise son tour d autres fonctions qui correspondent la notion de sous programmes Par exemple si vous d sirez calculer la somme des carr s de deux nombres vous d finirez d abord la fonction carr let carr x x x carr int gt int lt fun gt pour ensuite d finir la fonction d sir e let somme_des_carr s x y carr x carr y somme_des_carr s int gt int gt int lt fun gt et enfin l appliquer dans le cas qui vous int resse somme_des_carr s 3 4 int 25 En r sum une
26. Avez vous d j connu l amour Vos programmes s criraient plus Connaissez vous le grand amour simplement en Caml L amour comment l avez vous A mon avis la programmation c est facile rencontr non argent Avez vous des probl mes avec vos l Faute d argent c est douleur sans programmes pareille 1 Avez vous des probl mes d argent J L argent a beaucoup de connotations chameaux chameau continuez sur le sujet l Le chameau est un charmant animal d une Aimez vous beaucoup l argent grande sobri t non Avez vous peur de manquer d argent Le chameau est mon animal favori pas cam1 vous l Vous voulez dire les cigarettes Camel Certes le chameau est d un caract re un J ai entendu parler de ce remarquable peu difficile mais il en est de langage Caml charmants n est ce pas Tout ce que vous allez dire pourra tre Un chameau deux bosses ou un retenu contre vous dromadaire Sans Caml je ne serais pas l je refuse Qu avez vous de plus dire sur les donc d en parler chameaux A mon avis Caml est sans gal naime Ce langage Caml est clairement en avance M me pas un peu sur nombre de ses successeurs D testez vous carr ment Caml est puissant et quelle belle Pourquoi cette r pulsion syntaxe hein Aimer me semble un sentiment trange pas Caml
27. C droite jeu int gt unit lt fun gt La figure 5 1 montre le d roulement de jeu 3 5 9 Fonctionnelles complexes sur les listes Nous allons maintenant passer en revue un certain nombre de fonctionnelles clas siques sur les listes Elles sont d un emploi plus rare que celles que nous avons d j vues Nous les utiliserons dans les exemples les plus difficiles Vous pourrez alors vous reporter aux explications qui suivent Notion d abstraction de sch mas de programmes Vous vous souvenez sans doute que pour g n raliser les fonctions de tri du chapitre 4 et du pr sent chapitre il nous avait suffi de passer la comparaison en param tre Nous avions dit que nous avions abstrait l ordre Les fonctionnelles que nous allons d crire sont galement bas es sur la notion d abstraction Cependant dans ce cas il ne s agit pas d abstraire une fonction qui intervient dans le programme pour le g n raliser mais 92 Listes d abstraire un sch ma de programme c est dire une m thode de calcul commune plusieurs algorithmes Pour d gager cette m thode de calcul nous allons montrer plusieurs fonctions qui l utilisent Nous rappelons d abord le code des fonctions somme et produit d finies ci dessus puis nous crivons la fonction implose qui renvoie la concat nation de toutes les cha nes d une liste et enfin la fonction concat ne_listes qui concat ne toutes les listes d une liste de listes ce
28. Dans la colonne de gauche la red finition de x ne modifie en rien la valeur de x dans le corps de la fonction f En revanche droite l identificateur x est li une r f rence La valeur de x dans le corps de f change donc videmment apr s l affectation cependant x est toujours li la m me valeur la m me r f rence On constate ainsi que les fonctions qui utilisent des r f rences non locales sont susceptibles de changer dynamiquement de comportement au gr des affectations des r f rences qu elles emploient 3 7 Un programme utilisant des r f rences Un exemple r aliste d utilisation des r f rences nous est fourni par la fonction factorielle qui retourne le produit des nombres entiers inf rieurs ou gaux son argument Nous en avions donn la d finition r cursive suivante au chapitre 2 he 1 sin 0 nx n 1 sinon Voici une autre d finition dont nous admettrons qu elle est math matiquement quivalente QU n 1X2X Xx n 1 xn Cette d finition avec trois petits points est allusive et se traduit g n ralement par une impl mentation sur machine base de boucles et d accumulateurs Ainsi on d finira une r f rence pour accumuler les multiplications par les nombres plus petits que n durant lex cution d une boucle allant de 1 n chaque tour on multiplie le contenu actuel de l accumulateur par l indice de boucle courant accu i accu s
29. En premier lieu il faut conserver l esprit que le filtrage en Caml est structurel on ne peut utiliser dans les motifs que des constructeurs des constantes et des variables l exclusion des valeurs calcul es C est pourquoi les variables qui interviennent dans un motif ne servent jamais faire des tests mais au contraire lier des parties de la valeur filtr e Comparer par exemple la d finition erron e de la fonction est_un avec celle correcte de la fonction test_ _un let un 1 un int 1 let est_un function un gt true _ gt false Entr e interactive gt _ gt false T Attention ce cas de filtrage est inutile est_un a gt bool lt fun gt est_un 2 bool true let test_ _un x if x un then true else false test_ _un int gt bool lt fun gt test_ _un 2 bool false Le premier filtre de la fonction est_un comprend la variable un qui est sans rapport avec l identificateur un pr c demment d fini la valeur 1 Autrement dit le nom de la variable un est sans importance dans le filtrage de la fonction est_un on peut le remplacer par x ou y et le filtrage est quivalent x gt true _ gt false Contrairement ce que l utilisateur voulait sans doute exprimer la fonction est_un ne teste donc pas si son argument correspond la m me valeur que l identificateur un en fait la fonction est_un renvoie toujou
30. P lt gt vrai lt gt P Th or me pour toute proposition P P lt gt vrai lt gt P gt gt gt P lt gt faux lt gt non P Th or me pour toute proposition P P lt gt faux lt gt non P Les deux th or mes pr c dents se r crivent donc plus simplement gt gt gt P ou non P Th or me pour toute proposition P P ou non P gt gt gt non P et non P Th or me pour toute proposition P non P et non P En logique il est inutile de r p ter deux fois la m me chose P ou P c est P Et inutile d insister P et P c est aussi P gt gt gt P ou P lt gt P Th or me pour toute proposition P P ou P lt gt P gt gt gt P et P lt gt P Th or me pour toute proposition P P et P lt gt P Il est vident qu en supposant une hypoth se vraie on la d montre facilement P gt P De plus une proposition est toujours quivalente elle m me 224 D monstration de propositions gt gt gt P gt P Th or me pour toute proposition P P gt P gt gt gt P lt gt P Th or me pour toute proposition P P lt gt P On sait bien que P amp Q est synonyme de Q amp P mais nous le prouvons gt gt gt P lt gt Q lt gt Q lt gt P Th or me pour toutes propositions Q P P lt gt Q lt gt Q lt gt P On sait aussi que prouver l quivalence de deux propositions est quivalent prouver l
31. a int Supposons qu on crive f 1 f oui On emploiera deux fois le sch ma de type de f une fois avec une nouvelle variable t t int puis avec une autre variable t t2 int Une fois cette substitution de nouvelles inconnues dans le sch ma de type effectu e les deux occurrences de f sont munies d un type comme les autres non pas un sch ma et tout se d roule comme avant Dans notre exemple l application de f 1 engendre l quation t int tandis que l application de f la cha ne oui engendre l quation t2 string Les inconnues t et t2 re oivent ainsi une valeur et l on en d duit facilement que le type de l expression f 1 f oui est int int f 1 f oui int int 1 1 Les sch mas de types sont donc des artifices utilis s tr s ponctuellement par l algorithme de typage il ne les manipule pas directement pour r soudre les quations En effet quand on emploie un sch ma de type on remplace syst matiquement ses param tres par des inconnues normales L algorithme de r solution ne manipulera donc que des expressions de types comprenant des inconnues mais non pas des sch mas 342 Un synth tiseur de types Introduction des sch mas de types Nous avons vu que le synth tiseur de types avait deux activit s principales in troduire de nouvelles quations et de nouvelles inconnues et r soudre les syst mes d quations qu il a lui m me engendr
32. analogue dans l autre polyn me let rec ajoute_polyn mes_creux pi p2 match pi p2 with ls SAT PE O _ gt p2 ai degr i as mi restel a2 degr 2 as m2 reste2 gt if degr 1 degr 2 then ai a2 degr 1 ajoute_polyn mes_creux restei reste2 else if degr i lt degr 2 then mi ajoute_polyn mes_creux restei p2 else m2 ajoute_polyn mes_creux pi reste2 ajoute_polyn mes_creux int a list gt int a list gt int a list lt fun gt Le filtre a1 degr 1 as m1 reste1 a2 degr 2 as m2 reste2 est com plexe et n cessite une explication Il est clairement constitu de deux filtres analogues 86 Listes s par s par une virgule l un pour filtrer p1 et l autre pour filtrer p2 Examinons celui qui concerne p1 Le filtre a1 degr i as mi restei signifie que e p1 est une liste non vide dont la t te est filtr e par a1 degr i as m1 et le reste est nomm restel e la t te de p1 est donc un couple dont les composantes sont nomm es a1 et degr i e le couple lui m me a1 degr i est nomm m1 gr ce au filtre synonyme as mi Admirons au passage la puissance et l l gance du m canisme de filtrage Remarquez galement que les filtres sont essay s dans l ordre de pr sentation dans le filtrage Par exemple la valeur 1 sera filtr e par le premier filtre bien qu elle soit aussi filtrable par le second titre d exemple no
33. autre part il faut mettre le code qui construit le bloc d activation sur la pile La seule subtilit est dans l attribution des emplacements une variable locale de type tableau a un emplacement de type Local_direct puisque le tableau est allou plat dans la pile en revanche un param tre de type tableau a un emplacement de type Local_indirect puisque c est un pointeur vers le tableau pass en argument qui est empil passage par r f rence et non pas le tableau lui m me passage par valeur Fichier compil ml let alloue_ variable _ locale nom typ env profondeur_pile lprofondeur_pile taille_du_type typ let emplacement match typ with Integer Boolean gt Compilation 301 Local_indirect profondeur_pile Array _ _ _ gt Local_direct profondeur_pile in ajoute_variable nom typ typ emplacement emplacement env let alloue_param tres liste_des_param tres environnement let prof ref O in let env ref environnement in do_list function nom typ gt env ajoute_variable nom typ typ emplacement Local_indirect prof lenv prof prof taille_du_mot liste_des_param tres lenv let compile_proc dure env nom d cl let envi alloue_param tres d cl proc_param tres env in profondeur_pile taille_du_mot let env2 list_it alloue_variable_locale d cl proc_variables envi in printf P s n nom printf sub sp d sp n profondeur pile prin
34. changer franchement notre fa on d appr hender les programmes En effet il est extr mement difficile de comprendre comment la proc dure marche Au contraire il Notions de complexit 31 faut se demander pourquoi elle marche Le pourquoi est simple il est enti rement con tenu dans la figure 2 1 Si vous tes persuad du bien fond de la m thode de r solution que la figure sugg re et que vous tes convaincu que la proc dure hanoi impl mente correctement cette m thode alors ne cherchez pas plus loin vous avez tout compris Si en revanche vous essayez de suivre le d roulement des appels r cursifs et les per mutations d arguments qui se d roulent l ex cution de la proc dure par exemple en utilisant la trace de Caml vous serez vite perdu En fait m me si vous suiviez pr cautionneusement ce d roulement vous n en apprendriez pas plus si ce n est que a marche puisque vous constateriez que les bons arguments se mettent en place au bon moment pour produire les bons r sultats comme par miracle Il faut se d cider penser que ce suivi pas pas du d roulement des programmes est du ressort de la machine exclusivement Notre compr hension est de bien plus haut niveau elle con siste essentiellement prouver que le programme ne peut que marcher comment le programme parvient effectivement au bon r sultat ne nous regarde pas Il est heureux que cette noble activit de r flexion sur le bien fond d une m th
35. compile_arguments env arg1 arg2 reg in printf s r d r 44 r d n instr_pour_op op regi reg2 reg Acc s_tableau arg1 Constante cst gt let inf sup type_ l ments type_de_tableau env argi in compile_expr env arg1 reg begin match type_ l ments with Integer Boolean gt printf load r d 4 r d n reg val_const cst inf taille_du_mot reg Array _ _ _ gt let taille taille _du_type type_ l ments in printf add r d d r d n reg val_const cst inf taille reg end Acc s_tableau argi arg2 gt let inf sup type_ l ments type_de_tableau env argi in let reg1 reg2 compile_arguments env argi arg2 reg in if inf lt gt 0 then printf sub r 44 4 r d n reg2 inf reg begin match type_ l ments with Integer Boolean gt printf mult r 4 44 r d n reg2 taille_du_mot reg2 printf load r d r 44 r d n regi reg2 reg Array _ _ typ gt let taille taille_du_type type_ l ments in printf mult r d 44 r d n reg2 taille reg2 printf add r d r 4 r d n regi reg2 reg end and compile_arguments env arg1 arg2 reg_libre let b1 besoins env argi and b2 besoins env arg2 in if b1 lt b2 amp amp sans_interf rences env arg1 sans_interf rences env arg2 then begin let reg2 reg1 compile_arguments env arg2 arg1 reg_libre in regi reg2 end else begin compile_expr env arg1 reg_libre if b2 lt dernier_registre reg_libre then begin
36. en bas Side Side_Bottom enfin le cadre chantillon en bas de l espace restant libre Side Side_Bottom et avec une marge de 2 mm en haut et en bas PadY Millimeters 2 0 pour que ce soit plus joli 11 3 Un convertisseur de devises Notre prochain exemple est d actualit il s agit d une calculatrice de conversion francs euros Elle introduit plusieurs nouveaux types de composant les zones d entr e dans lesquelles l utilisateur peut taper et diter un texte les tiquettes les menus d roulants Elle illustre galement le m canisme g n ral de liaison de CamlTk qui permet d associer une action Caml presque n importe quel type d v nement appui de touche clic de souris mouvement de la souris etc La calculatrice se compose de deux zones d entr e l une pour FR les francs l autre pour les euros D s que l utilisateur modifie le ee ln montant figurant dans l une des zones ce montant est converti dans l autre monnaie et affich dans l autre zone Nous commen ons par la fonction centrale de l application qui assure cette mise jour automatique d une zone d entr e le param tre dest lorsque l autre zone le param tre source change let synchronise_ zones source dest taux_source taux_dest function infos gt try let montant_source float_of_string entry__get source in let montant_dest montant_source taux_source taux_dest in entry__delete_range dest
37. entiers Fichier ensent ml type t int list let vide l let rec appartient n function O gt false m reste gt Mise en pratique 321 if m n then true else if m gt n then false else appartient n reste let rec ajoute n function gt in m reste as ens gt if m n then ens else if m gt n then n ens else m ajoute n reste Comme la liste est tri e par ordre croissant on arr te la recherche ou l insertion d s qu on atteint un l ment plus grand que l entier rechercher ou ins rer L insertion et la recherche sont donc en temps moyen n 2 et en temps le pire n si n est le nombre d l ments de l ensemble 16 8 Mise en pratique Il ne reste plus qu compiler tous les modules de la commande grep et les lier entre eux camlc c expr mli camlc c expr ml camlc c auto mli camlc c auto ml camlc c ensent mli camlc c ensent ml camlc c determ mli camlc c determ ml camlc c grep ml camlc o grep expr zo auto zo ensent zo determ zo grep zo lt A A a a En guise d exemple voici comment rechercher tous les mots qui contiennent la lettre p suivie de la lettre x dans un fichier camlrun grep pPlla zl xx fichier L ex cution de cette commande sur le texte de ce chapitre d tecte quatre occurrences du mot postfixe et deux de prix 16 9 Pour aller plus loin La rapidit
38. est faux nul r2 est mis vrai si r est vrai non nul r2 est mis faux Exemple d application le test strictement plus grand entre un registre r et un registre ou une constante o avec r sultat dans r2 se calcule par les deux instructions sle 71 0 72 seq Tr2 r 0 72 La premi re instruction calcule la n gation du r sultat d sir la n gation de r gt o est r lt o la deuxi me calcule la n gation de cette n gation obtenant le r sultat d sir Le pico processeur 259 Sous programmes L instruction jmp sert la fois pour appeler un sous programme et pour revenir d un sous programme dans le programme principal L id e est de passer au sous programme son adresse de retour dans un registre particulier Par convention nous utiliserons toujours le registre r 31 pour passer l adresse de retour et les registres r 1 r 2 pour passer les arguments et les r sultats entre un sous programme et le programme qui l appelle Ce n est qu une convention dans le but de rendre les programmes plus lisibles rien dans l architecture de la pico machine n impose ce choix de registres Avec cette convention voici comment s crit la fonction moyenne arithm tique Instruction 100 add r 1 r 2 r i 104 divr1i 2 ri 108 jmp r 31 ro Et voici un programme d d essai qui appelle cette fonction Instruction 0 scall 0 lecture d un nombre au clavier 4 add r 1 O r 2
39. est pourquoi il nous suffit de d finir une fonction r cursive l int rieur de map qui saura appliquer f sur les l ments d une liste quelconque let map f let rec map_fonction_f function o gt 0 x 1 gt f x map_fonction_f 1 in function liste gt map_fonction_f liste map a gt b gt a list gt b list lt fun gt 98 Listes Ainsi map n est plus r cursive mais comporte une d finition locale de fonction r cursive On simplifie encore ce code en utilisant la r gle 7 qui stipule que function liste gt map_fonction_f liste est quivalent la forme plus simple map_fonction_f On obtient alors le code suivant let map f let rec map_fonction_f function o gt 0 x 1 gt f x map_fonction_f 1 in map_fonction_f map a gt b gt a list gt b list lt fun gt Cette vision de map correspond celle d une fonctionnelle qui appliqu e une fonction f retourne la fonction qui it re f sur une liste Avec cette vision nous pourrions crire let successeur x x 1 successeur int gt int lt fun gt let liste_des_ successeurs map successeur liste_des_successeurs int list gt int list lt fun gt liste_des_successeurs 0 1 2 int list 1 2 3 Ce style de programmation n est pas encourager la d finition na ve de map nous para t plus claire D autre part la d finition de map av
40. exemple ci dessus nous avons utilis d qui convertit un entier en d cimal Dans la fonction rafra chir_couleur nous utilisons 02x qui convertit un entier en hexad cimal x sur deux chiffres 2 en compl tant gauche avec des z ros si n cessaire 0 Enfin nous changeons la couleur de fond du cadre chantillon l aide de la fonction frame__configure De mani re g n rale toutes les options qui peuvent tre sp cifi es au moment o l on cr e un composant en second argument de com posant__create peuvent aussi tre sp cifi es ou modifi es plus tard via la fonction composant__configure Mettant imm diatement ce principe en pratique nous utilison scale__configure pour associer la fonction rafra chir_couleur au d placement de chacune des glissi res scale__configure rouge ScaleCommand rafra chir_couleur scale__configure vert ScaleCommand rafra chir_couleur scale__configure bleu ScaleCommand rafra chir_couleur pack rouge vert bleu Side Side_Top l 196 Interfaces graphiques pack quitter Side Side_Bottom l pack chantillon Side Side Bottom PadY Millimeters 2 0 mainLoop Comme dans le premier exemple nous pla ons finalement tous les composants l aide de pack puis lan ons l interaction avec l utilisateur en appelant mainLoop Le place ment se fait en trois temps d abord les trois glissi res en haut de la fen tre Side Side_Top puis le bouton Quitter
41. false let crayon x 0 0 y 0 0 vis e 0 0 lev crayon tat x 0 0 y 0 0 vis e 0 0 lev Tourner Faire tourner le crayon consiste changer son angle de vis e pour lui im primer le nouveau cap On utilise pour cela la modification physique d un champ d enregistrement not e par une fl che vers la gauche lt Ainsi la fonction qui permet de lever ou de baisser le crayon est simplement let fixe_crayon b crayon lev lt b fixe_crayon bool gt unit lt fun gt L angle de vis e crayon vis e est exprim en radians et suit les conventions du cercle trigonom trique des math matiques le z ro est l est et le crayon tourne dans le sens inverse de celui des aiguilles d une montre On rappelle que le cercle trigonom trique est le cercle de rayon 1 d un rep re orthonorm Si l angle 0 est rep r par les demi droites Ox et OM alors les coordonn es x y de M sont respectivement le cosinus et le sinus de l angle 6 Le crayon lectronique 151 Cependant pour plus de commodit les or dres de changement de cap donn s au crayon seront exprim s en degr s La conversion est simple puisqu on a Angle en radians Angle en degr s x 7 180 Apr s avoir nomm M la valeur 7 180 pour faire commod ment les conversions de degr s en radians nous RE ol g Fi d finissons la fonction tourne qui change le cap D hp du crayon cos 6 let pi_sur_180 le
42. gt num ro_de_compte num ro_de_compte 1 num ro num ro_de_compte solde d pot cr e_compte float gt compte lt fun gt let compte_de_dupont cr e_compte 500 0 compte_de_dupont compte num ro 1 solde 500 0 let compte_de_duval cr e_compte 1000 0 compte_de_duval compte num ro 2 solde 1000 0 Il faut bien comprendre que la r f rence num ro_de_compte est cr e une seule fois lors de la construction de la fonction cr e_compte chaque appel de cr e_compte on retrouve ainsi dans num ro_de_compte la derni re valeur qui y a t inscrite Les 120 Les structures de donn es variables de ce genre sont appel es variables r manentes dans la litt rature informatique et variables statiques en C Remarquez que Caml les autorise sans avoir besoin de fournir une construction sp ciale pour cela le let in habituel et les fonctions anonymes suffisent pour programmer des variables r manentes 6 7 Structures de donn es et filtrage Comme nous l avons vu maintes reprises le filtrage va de paire avec les d finitions de structures de donn es Bien plus la d finition d un type sert de guide pour crire le squelette du filtrage des fonctions qui op rent sur ce type Nous voulons cependant attirer votre attention sur quelques traits avanc s du filtrage et quelques cueils qui guettent les d butants qui crivent leurs premiers filtrages Filtrage de valeurs calcul es
43. let fst x y x fst a b gt a lt fun gt let snd x y y snd a b gt b lt fun gt Une fois de plus le polymorphisme nous autorise d finir ces deux fonctions pour tous les types de paires La fonction menu est maintenant sans surprises let menu invites_options for i 0 to vect_length invites_options 1 do print _string lt string_of_int i gt print_string fst invites_options i done print_newline print_string Choisissez votre option let r ponse read_int in snd invites_options r ponse menu string unit gt a vect gt a lt fun gt menu Arr ter au_revoir Continuer continuer Ne rien faire function gt I lt 0 gt Arr ter lt 1 gt Continuer lt 2 gt Ne rien faire Choisissez votre option 0 Au revoir unit Un menu polymorphe tr s g n ral R fl chissons encore un peu sur la proc dure menu la quintessence de cette proc dure n est pas d appliquer directement les options mais plut t de retourner un certain l ment d un tableau d options selon la r action de l utilisateur aux propositions affich es Un pas de plus dans la g n ralisation consiste donc ne pas consid rer que les options doivent forc ment tre des proc dures On se contente alors de retourner le deuxi me l ment du couple correspondant au message d invite choisi
44. let identit x x identit a gt a lt fun gt Nous obtenons encore une fonction polymorphe Notez que le type de la fonction identit indique juste titre que le type du r sultat est exactement celui de l argument Le param tre a remplace n importe quel type en particulier string ou int l gitimant ainsi l emploi de identit avec le type string gt string et aussi avec le type int gt int identit non identit 1 string non sui int 1 Fonctions d ordre sup rieur 59 Ce m canisme de remplacement d un param tre de type par un type quelconque s appelle la sp cialisation Nos deux exemples consistent donc sp cialiser a en string puis en int On n est pas oblig de sp cialiser un param tre avec un type de base comme nous l avons fait jusqu pr sent on le sp cialise tout aussi bien avec un type complexe par exemple int gt int Dans le cas de la fonction identit on obtient le type int gt int gt int gt int Cela sugg re d appeler la fonction identit sur un argument qui est lui m me une fonction et pourquoi pas la fonction successeur identit successeur int gt int lt fun gt La fonction identit renvoie toujours son argument sans modification elle renvoie donc tout simplement la fonction successeur quand on l applique successeur Par exemple let success identit successeur success int gt int
45. let sigma formule n let r sultat ref O in for i O0 to n do r sultat r sultat formule i done lr sultat sigma int gt int gt int gt int lt fun gt ou m me l aide d une fonction r cursive let rec sigma formule n if n lt 0 then 0 else formule n sigma formule n 1 sigma int gt int gt int gt int lt fun gt Nous pouvons maintenant faire calculer par Caml les exemples que nous avions donn s Si la formule est r duite on obtient la somme des nombres de 0 n n Ji 0 1 n i 0 Cette formule correspond appeler la fonctionnelle sigma avec l argument function i gt i sigma function i gt i 10 sigma identit 10 int 55 int 55 De m me la somme des carr s des nombres entre 0 et n n yr EAE OE i 0 s obtient par application de sigma l argument function i gt i i sigma function i gt i i 10 int 385 4 3 Typage et polymorphisme Synth se du type le plus g n ral Comme nous l avons d j dit le compilateur de Caml donne un type chaque phrase entr e par l utilisateur cette inf rence de types ne n cessite aucune participation de 62 Fonctionnelles et polymorphisme l utilisateur elle se produit automatiquement sans n cessit d indiquer les types dans les programmes Connaissant les types des valeurs de base et des op rations primitives le contr leur de types produ
46. lt proposition2 p reste3 p q gt gt q and reste3 p function lt MC ou proposition q reste3 Ou p q r gt gt r lt gt gt p and proposition4 function lt proposition3 p reste4 p q gt gt q and reste4 p function lt MC gt proposition3 q reste4 Implique p q r gt gt r lt gt gt p and proposition5 function lt proposition4 p reste5 p q gt gt q and reste5 p function lt MC lt gt proposition4 q reste5 quivalent p q r gt gt r lt gt gt p Les fonctions proposition1 proposition5 sont toutes construites sur le m me moule Elles cherchent d abord une proposition de niveau plus simple puis appellent une fonction reste Cette fonction se charge de d tecter l op rateur par exemple et pour reste2 suivi d une proposition de m me niveau et ventuellement d autres op rateurs du m me type d autres et pour reste2 Remarquez que la fonction reste prend en argument l arbre de syntaxe abstraite jusqu pr sent construit et lui ajoute les op rateurs rencontr s d o l appel reste2 p dans la fonction proposition et l appel r cursif reste2 Et p q dans la fonction reste2 220 D monstration de propositions La similitude entre les fonctions qui g rent les priorit s des op rateurs sugg re d crire une fonction g n rique qui prenne en argument l op rateur binaire r
47. lt fun gt success 3 int 4 4 2 Fonctions d ordre sup rieur Les fonctions d ordre sup rieur sont des fonctions dont les arguments ou les r sultats sont eux m mes des fonctions Une fonction d ordre sup rieur est encore appel e une fonctionnelle Ces fonctions sont souvent polymorphes et surtout employ es avec des structures de donn es plus complexes que les types de base Il n est pas n cessaire de tout conna tre sur le polymorphisme et les fonctions d ordre sup rieur pour les utiliser Pour le lecteur plus int ress par les programmes que par la th orie il suffit donc de lire cette section pour comprendre le reste des exemples de ce livre Nous commencerons par les fonctions qui renvoient d autres fonctions puis nous verrons les fonctions dont les arguments sont fonctionnels Les exemples pr sent s ici seront sans doute un peu artificiels puisque nous ne disposons pas encore des outils suffisants pour montrer des utilisations r alistes de fonctionnelles sur des structures de donn es complexes Fonctions retournant des fonctions Supposez que nous voulions d finir la fonction fois_x qui tant donn un entier x fabrique la fonction qui multipliera par x La d finition en pseudo code Caml serait let fois_x x la fonction qui multiplie par x Nous crivons donc du vrai code pour la p riphrase la fonction qui multiplie par x let fois_x x function y gt x y fois_x in
48. met la lettre correspondante et on repart de la racine de l arbre Cet algorithme s crit sans difficult s en Caml On a introduit un second type de feuille le constructeur Fin pour repr senter le code de fin de fichier Fichier huffman ml type arbre_de_huffman Lettre of char Fin Noeud of arbre_de_huffman arbre_de_huffman let d code entr e sortie arbre esbit__initialise let rec parcours function Fin gt O Lettre c gt output_char sortie c parcours arbre Noeud gauche droite gt if esbit__lire_bit entr e 0 then parcours gauche else parcours droite in parcours arbre D termination d un codage adapt On peut utiliser les fonctions encode et d code avec un codage de Huffman fix d termin une fois pour toutes partir des fr quences moyennes d apparition des car act res dans les textes fran ais par exemple Cependant la compression risque d tre peu efficace sur d autres types de textes des programmes Caml par exemple ou sur des fichiers contenant autre chose que du texte des images num ris es par exemple Pour plus de g n ralit il vaut mieux d terminer les fr quences des caract res dans 244 Compression de fichiers le fichier compresser puis construire un codage de Huffman adapt cette distribu tion de fr quence particuli re Bien entendu le d compresseur ne peut pas deviner le codage que le compresseur a utilis le compre
49. se lit donc comme un espace une tabulation ou un caract re de fin de ligne Poursuivons dans la m me veine par la fonction qui lit des entiers let rec lire_entier accumulateur flux match flux with lt f0 9 as c gt gt lire_entier 10 accumulateur int_of_char c 48 flux lt gt gt accumulateur lire_entier int gt char stream gt int lt fun gt Le motif 0 9 filtre tous les caract res entre 0 et 9 dans le jeu de caract res ASCII c est dire tous les chiffres C est une abr viation pour 0 1 1 2 1f3 1 4f 5 6 1 7 1 8 1 9 Que dit la fonction lire_entier Si le premier caract re de flux est un chiffre alors se rappeler r cursivement pour lire la suite du nombre entier sinon s arr ter et renvoyer l entier lu jusqu ici Le param tre accumulateur est la valeur enti re du nombre que repr sentent les chiffres lus jusqu ici Les chiffres ont les codes 48 164 Syntaxe abstraite syntaxe concr te 57 en ASCII donc int_of_char c 48 est l entier entre z ro et neuf qui repr sente le chiffre c L appel r cursif sur 10 accumulateur int_of_char c 48 revient bien introduire le chiffre c droite du nombre accumulateur Exemple d ex cution let flux_car stream _of_string 123 456 flux_car char stream lt abstr gt lire_entier 0 flux_car int 123 stream_next flux _car char lire_en
50. tat en z ro epsilon transitions En une ou plusieurs transitions on passe d abord par un tat e accessible partir de e par une epsilon transition puis on atteint un des tats appartenant la fermeture de e Cela sugg re la d finition suivante de la fonction fermeture fermeture e est l union du singleton e et des ensembles fermeture e pour e d crivant e epsilon_transitions Cette d finition est incorrecte cause des cycles possibles par exemple si e poss de une epsilon transition vers e qui a une epsilon transition vers e Pour contourner cette difficult l id e est de garder un ensemble des tats qu on sait d ores et d j appartenir la fermeture S il se pr sente un tat e qui n est pas dans cet ensemble on l ajoute et on examine r cursivement tous les tats de e epsilon_transitions Si l tat e est d j dans cet ensemble il n y a rien faire La fonction ajoute_fermeture impl mente cet algorithme Les fonctions fermeture et fermeture_ens sont de simples applications de fermeture obtenues en prenant l ensemble vide comme ensemble d tats d j vus Fichier determ ml let d placements liste_ tats let t make_vect 256 vide in do_list function tat gt do_list function car dest gt let i int_of_char car in t i lt ajoute dest t i tat transitions liste_ tats t La fonction d placements ci dessus calcule toutes les transitions possi
51. une fonction carr carr x puissance4 int gt int lt fun gt puissance4 3 int 81 Comme on le voit sur cet exemple les commentaires en Caml sont encadr s entre x et Ils peuvent contenir n importe quel texte y compris d autres commentaires et s tendre sur plusieurs lignes Fonctions plusieurs arguments Les fonctions poss dant plusieurs arguments ont simplement plusieurs noms d arguments dans leur d finition let moyenne a b a b 2 moyenne int gt int gt int lt fun gt let p rim tre_du_rectangle longueur largeur 2 x longueur largeur p rim tre_du_rectangle int gt int gt int lt fun gt Le type de ces deux fonctions int gt int gt int indique qu elles prennent deux arguments de type int int gt int gt et calculent un entier gt int Lorsque des fonctions ont plusieurs arguments il faut videmment leur fournir aussi leur compte d arguments quand on les applique Ainsi un appel p rim tre _du_rectangle ou moyenne comportera deux arguments p rim tre_du_rectangle 3 2 int 10 moyenne 5 3 int 4 Fonctions 11 Fonctions anonymes Une fonction Caml est un citoyen part enti re on dit aussi citoyen de premi re classe c est dire une valeur comme toutes les autres Une fonction a le m me statut qu un nombre entier elle est calcul e on peut la passer en argument ou
52. une fonction plus g n rale sont monomor phes Nous avons d j constat page 73 que l application de la r gle 7 peut modifier le type d une fonction le rendant plus g n ral ici c est l inverse on passe d un type polymorphe un type monomorphe moins g n ral 5 8 Animation des tours de Hanoi En guise d exercice sur les listes nous d finissons un ensemble de fonctions qui ma nipulent des listes de cha nes pour animer visuellement le jeu des tours de Hanoi C est un vrai programme qui utilise des r f rences et la r cursivit Cela reste cependant un exercice nous n avons aucun souci d efficacit ici Ce genre de programme d impression labor e le formatage est plus du ressort de la modification physique de cha nes de caract res que de la manipulation de listes let blancs n make_string n blancs int gt string lt fun gt let disque taille let moiti _droite make_string taille gt and moiti _gauche make_string taille lt in moiti _gauche moiti _droite disque int gt string lt fun gt Ces deux fonctions construisent respectivement la repr sentation sous forme d une cha ne d une ligne vide de longueur n et d un disque de largeur taille Par exemple le disque de largeur 3 est repr sent par la cha ne lt lt lt gt gt gt 1a cha ne repr sente un morceau de tige et lt lt lt et gt gt gt les parties gauche et
53. valuation de la fonction Pour l application d une fonction son argument on value fonction et argument et l on teste si la fonction renvoy e est bien une fonction c est dire soit une fermeture soit une primitive Dans le cas d une primitive on applique directement la valeur fonc tionnelle impl mentant la primitive Dans le cas d une fonction on essaye de filtrer la valeur de l argument par les motifs des diff rents cas de la fonction Le premier filtrage qui r ussit provoque l valuation de l expression associ e dans un environnement qui est l environnement contenu dans la fermeture enrichi par les liaisons effectu es lors du filtrage Fichier eval ml let rec value env expr match expr with Variable id gt begin try assoc id env with Not_found gt raise Erreur id est inconnu end Fonction liste_de_cas gt Val_fermeture d finition liste_de_cas environnement env Application fonction argument gt let val_fonction value env fonction in let val_argument value env argument in begin match val_fonction with Val_ primitive fonction primitive gt fonction_primitive val_argument Val_fermeture fermeture gt value_application fermeture environnement fermeture d finition val_argument _ gt raise Erreur application d une valeur non fonctionnelle end 330 Ex cution d un langage fonctionnel Let d finition corps gt value value_d
54. vons donc commencer l impl mentation des op rations l mentaires sur les polyn mes Commen ons par crire une proc dure d impression des polyn mes pour visualiser simplement nos r sultats Il suffit de parcourir le tableau repr sentant le polyn me en imprimant ses mon mes Nous crivons donc d abord la fonction d impression d un Impression des polyn mes 43 mon me de coefficient c et de degr d C est tr s simple si le degr est 0 il suffit d crire le coefficient sinon on crit le coefficient et le degr sous la forme cX d Par exemple 3x sera crit 3x2 Cet imprimeur n est pas tr s labor il se contente de ne pas crire les mon mes nuls ni les coefficients gaux 1 il traite aussi sp cialement le cas particulier des mon mes de degr 0 et 1 Ainsi il crit x 2 pour le mon me 1x 3 pour le mon me 3x et 4x pour le mon me 4x let imprime_mon me coeff degr if degr 0 then print_int coeff else if coeff lt gt 0 then begin print _string if coeff lt gt 1 then print_int coeff print_string x if degr lt gt 1 then begin print_string print_int degr end end imprime_mon me int gt int gt unit lt fun gt La primitive lt gt correspond au pr dicat math matique et teste donc si deux valeurs sont diff rentes Il est temps de donner le nom technique des polyn mes mod lis s par des tableaux d entiers on les appelle polyn mes plei
55. y fin On regroupe ensuite les arbres de fr quences 30 et 25 puis 31 et 40 puis 55 et 60 En regroupant les deux arbres restants on obtient enfin l arbre de Huffman recherch L algorithme de Huffman 245 186 Traduisons maintenant cet algorithme en Caml Fichier huffman ml let construire_arbre fr quences let prio ref fileprio__ajoute fileprio__vide 1 Fin in let nombre_d arbres ref 1 in for c 0 to 255 do if fr quences c gt 0 then begin prio fileprio__ajoute prio fr quences c Lettre char_of_int c incr nombre_d arbres end done for n nombre_d arbres downto 2 do let fr qi arbrel priol fileprio__extraire prio in let fr q2 arbre2 prio2 fileprio__extraire priol in prio fileprio__ajoute prio2 fr qi fr q2 Noeud arbrei arbre2 done let _ arbre _ fileprio__extraire prio in arbre Pour g rer l ensemble d arbres et les fr quences associ es on a utilis les fonctions d un module fileprio impl mentant la structure de donn es connue sous le nom de file d attente avec priorit Voici l interface de ce module Fichier fileprio mli type at value vide a t and ajoute a t gt int gt a gt at and extraire a t gt int a a t exception File_vide Les deux op rations de base sur une file d attente avec priorit sont l ajout d un l ment dans la file avec une certaine priorit
56. 0 Il s agit d un programme permettant de choisir 1 des couleurs l cran et jouant sur les intensit s W des trois couleurs primaires rouge vert bleu IHH Trois glissi res contr lent ces intensit s d s que CE l utilisateur d place l une des glissi res la couleur correspondante est affich e dans le rectangle en bas Quitter de la fen tre let fen tre _ principale openTk let cr er_glissi re nom scale__create fen tre_principale Label nom From 0 0 To 255 0 Length Centimeters 10 0 Orient Horizontal let rouge cr er_glissi re Rouge and vert cr er_glissi re Vert and bleu cr er_glissi re Bleu and chantillon frame__create fen tre _principale Relier des composants entre eux 195 Height Centimeters 1 5 Width Centimeters 6 0 and quitter button__create fen tre_principale Text Quitter Command closeTk Nous commen ons par cr er trois glissi res scale pour chacune des couleurs primaires rouge vert et bleu Ces glissi res prennent des valeurs entre 0 et 255 From 0 0 To 255 0 ont une longueur de 10 cm Length Centimeters 10 0 et sont orient es dans le sens horizontal Orient Horizontal Pour afficher la couleur nous cr ons galement un cadre frame qui est une zone inactive de 6 cm sur 1 5 cm Height Centimeters 1 5 Width Centimeters 6 0 Enfin le dernier composant du programme est un bouton tiquet Quitter dont l action closeTk
57. 144 mult r 1 r 2 r 1 calculen x n 1 dansr 1 148 jmp r 31 r O retour l appelant 14 2 Le simulateur Nous passons maintenant l impl mentation en Caml d un simulateur de la pico machine Cette impl mentation se compose de deux programmes l un le simulateur proprement dit prend une repr sentation binaire du code ex cuter et l ex cute l autre appel l assembleur produit la repr sentation binaire ex cutable partir d un texte de programme crit dans le langage de la pico machine Nous tudierons l assembleur dans la section 14 3 pour l instant voyons le simulateur Description du pico processeur On commence par un module code qui d finit le jeu d instructions de la machine sous forme d un type concret Caml ainsi que certaines caract ristiques de la machine Fichier code mli type registre int type op rande Reg of registre Imm of int type instruction Op of op ration registre op rande registre Jmp of op rande registre Braz of registre int Branz of registre int Le simulateur 261 Scall of int Stop and op ration Load Store Add Mult Sub Div And Or Xor Shl Shr Slt Sle Seq value nombre_de_registres int and sp int and ra int and taille _du_ mot int Les instructions sont d crites par un ensemble de types somme et une abr viation de type type registre int Une abr viation de type
58. A nsi quel que soit le niveau de d tail o on l examine la fractale pr sente toujours son motif Le flocon de von Koch est d fini partir du motif suivant Ce motif est ensuite reproduit sur chacun des c t s du motif de base chelle r duite ce qui donne VAN A La g n ration suivante sera donc ri Ce m canisme est reproductible l infini en math matiques Nous nous contenterons videmment d atteindre la r solution maximale de l cran Le flocon de von Koch proprement dit s obtient simplement en reproduisant trois fois le motif sur les trois c t s d un triangle quilat ral La premi re g n ration donne donc le dessin ci contre 148 Graphisme Afin de dessiner le flocon nous allons impl menter un crayon programmable ver sion simplifi e de la tortue du langage Logo Nous pourrons ensuite programmer ses d placements sur l cran pour qu il trace le flocon 8 2 Le graphisme de Caml Le crayon se d place dans le rep re du graphisme de Caml Ce rep re a la forme suivante axe des y size_y cran y point en x y axe des x point en 0 0 pa size_x L origine est donc en bas gauche de l cran La taille de l cran en x et en y est donn e par les primitives size_x et size_y Le graphisme de Caml utilise les notions de point courant et de couleur de trac courante L ordre lineto x y trace une ligne de la couleur courante joignant le point couran
59. Le module correspondant s appelle auto voici son interface Des expressions rationnelles aux automates 311 Fichier auto mli open expr type tat mutable transitions char tat list mutable epsilon_ transitions tat list mutable terminal bool num ro int value expr_vers_automate expr gt tat Un tat de l automate est repr sent par un enregistrement quatre champs Le champ terminal indique si l tat est terminal ou non Les champs transitions et epsilon_transitions contiennent la liste des fl ches sortant de l tat avec pour chaque fl che l tat auquel elle m ne Le champ num ro sert identifier les tats de mani re unique deux tats diff rents portent des num ros diff rents L automate lui m me est repr sent par son tat initial Les autres tats de l automate pendent sous l tat initial ils sont accessibles en descendant dans les champs transitions et epsilon_transitions L impl mentation du module auto comporte deux parties premi rement quelques petites fonctions de manipulation des tats deuxi mement la fonction de compilation d une expression rationnelle en automate Fichier auto ml open expr let compteur_d tats ref 0 let nouvel_ tat incr compteur_d tats transitions l epsilon_ transitions terminal false num ro compteur_ d tats let ajoute_trans ni c n2
60. Les d finitions 7 D finitions globales De m me qu en math matiques on crit soit s la somme des nombres 1 2 et 3 on crit en Caml soit se traduit par let en anglais let s 1 2 3 s int 6 Caml nous r pond que nous avons d fini un nouveau nom s qui est de type entier int et vaut 6 6 Maintenant que le nom s est d fini il est utilisable dans d autres calculs par exemple pour d finir le carr de s on crirait let s2 s s s2 int 36 Les d finitions sont des liaisons de noms des valeurs On peut consid rer ces noms qu on appelle aussi identificateurs ou encore variables comme de simples abr viations pour la valeur qui leur est li e En particulier une d finition n est pas modifiable un nom donn fait toujours r f rence la m me valeur celle qu on a calcul e lors de la d finition du nom Le m canisme du let est donc fondamentalement diff rent du m canisme d affectation que nous tudierons plus loin Il est impossible de changer la valeur li e un nom on peut seulement red finir ce nom par une nouvelle d finition donc un nouveau let Une fois d fini un nom a toujours la m me valeur Informatique et math matiques La grande diff rence entre les math matiques et les langages de programmation m me ceux qui se rapprochent des math matiques comme Caml est qu un langage de programmation calcule avec des valeurs et non pas avec
61. MC ou Le constructeur MC est l abr viation de mot cl Autant les conventions lexicales de base qu est ce qu un entier qu est ce qu un iden tificateur sont souvent les m mes d un langage un autre autant les mots cl s sont hautement sp cifiques au langage Dans le but de rendre notre analyseur lexi cal r utilisable par la suite pour d autres langages que les propositions nous n allons 218 D monstration de propositions pas mettre en dur la liste des mots cl s dans le code de l analyseur Au contraire l analyseur va prendre en param tre la liste des mots cl s et renvoyer une fonction d analyse lexicale de type char stream gt lex me stream sp cialis e pour cette liste de mots cl s La fonction principale qui fait correspondre une fonction d analyse une liste de mots cl s est plus qu un analyseur lexical c est toute une famille d analyseurs lexicaux en puissance C est pourquoi nous l appelons g n rateur d analyseurs lexi caux ou analyseur lexical universel Les mots g n rateur et universel sont un peu forts car cette fonction impose des conventions lexicales fixes elle n est donc pas universelle et ne remplace en aucun cas un v ritable g n rateur d analyseurs comme camllex cf le chapitre 7 du Manuel de r f rence du langage Caml Pourtant cet analyseur lexical universel suffira amplement aux besoins de ce livre c est le dern
62. Si P est une proposition et Q est une proposition alors P et Q est une proposition Par d finition P et Q n est vraie que si P et Q sont simultan ment vraies La proposition P et Q est not e P A Q en math matiques L op ration et est aussi d finie par une table de v rit mais le tableau comporte plus de lignes que pour l op ration non car il faut envisager tous les cas possibles pour P et pour Q c est dire quatre cas P QIP v v v vj f f fjv f IIF f Remarquez que P et Q est fausse d s que l une des propositions P ou Q est fausse Le ou est sym trique du et en rempla ant vrai par faux par d finition P ou Q n est fausse que si P et Q sont simultan ment fausses La proposition P ou Q est not e P V Q en math matiques P Q PouQ vu v v vI f U flv v IJF f Remarquez que P ou Q est vraie d s que lune des propositions P ou Q est vraie Ce sont les seules d finitions n cessaires en logique l mentaire Toutes les autres constructions du raisonnement s expriment en fonction de celles ci Cette conomie de moyens est l une des beaut s de la logique Toute la th orie est construite sur les notions l mentaires et intuitives de valeur de v rit de et de ou et de non Remarques sur les connecteurs et et ou Il faut noter que le ou de la logique est inclusif c est dire que P ou Q est encore vr
63. assemble 0p test ri o r2 assemble 0p Seq r2 Reg 0 r2 lt MC jmp op rande o MC registre r gt gt assemble Jmp o r lt MC braz registre r MC constante c gt gt assemble Braz r c lt MC branz registre r MC constante c gt gt assemble Branz r c lt MC scall Entier n gt gt assemble Scall n lt MC write gt gt assemble Scall 1 lt MC read gt gt assemble Scall 0 lt MC stop gt gt assemble Stop and reg_op_reg function lt registre ri MC op rande o MC registre r2 gt gt ri o r2 and op ration function lt MC load gt gt Load lt MC store gt gt Store lt MC add gt gt Add lt MC mult gt gt Mult lt MC sub gt gt Sub lt MC div gt gt Div lt MC and gt gt And lt MC or gt gt Or lt MC xor gt gt Xor lt MC shl gt gt Shl lt MC shr gt gt Shr lt MC slt gt gt Slt lt MC sle gt gt Sle lt MC seq gt gt Seq and test_invers function lt MC sgt gt gt Sle lt MC sge gt gt Slt L assembleur 273 lt MC sne gt gt Seqg let d finition _d tiquette function lt Ident nom tiq MC gt gt poser_ tiquette nom_ tiq let rec instruction_ tiq functio
64. autre part nous avons 6 Premiers pas d j vu que Caml est un langage typ Ces notions sont simplement g n ralis es et simplifi es par exemple le typage est automatique et ne n cessite pas d annotations dans les programmes comme c est le cas en Pascal 1 2 Dialoguer avec Caml Caml offre non seulement un compilateur traditionnel qui transforme des fichiers de code source en code compil ex cutable par la machine mais aussi un syst me interactif qui vous permet de dialoguer directement avec Caml sans passer par l interm diaire d un fichier Dans ce mode le langage s utilise comme une calculette vous tapez des phrases au clavier de l ordinateur et Caml r agit en vous donnant imm diatement les r sultats de vos programmes Nous utiliserons d abord cette m thode d interaction di recte car elle facilite l apprentissage Nous verrons plus tard l utilisation du compilateur ind pendant partir du chapitre 10 Vous pouvez donc entrer au terminal les exemples qui suivent si vous avez d j install le syst me Caml Light sur votre machine Toutes les phrases soumises Caml doivent tre munies d une indication de fin de phrase ce qu on note en Caml par deux points virgules accol s C est justifi pour un syst me qui offre une version interactive dans la mesure o il est impossible de deviner quand l utilisateur a termin sa phrase par exemple apr s 1 2 il est permis d crire en
65. avantage de mettre 1 en vidence la construction de la liste partir de ses D N l ments de la liste vide et d applications successives du 3 SF constructeur En effet la liste trois_entiers vaut 1 2 3 et vous aurez sans doute remarqu l que la notation e1 e2 en est une abr viation pour e1 2 En L Lorsque nous expliquerons des ei fonctions sur les listes la liste argument la plus g n rale Es sera not e l et ses l ments seront not s e1 2 En 7 Cette liste la plus g n rale sera donc d crite graphique 4 J ment par le peigne en marge Filtrage des listes Le filtrage est tendu aux listes si bien qu on teste si une liste est vide avec la fonction suivante let nulle function gt true _ gt false nulle a list gt bool lt fun gt Ce texte Caml se lit comme suit si l argument de la fonction nulle est la liste vide alors retourner true gt true dans tous les autres cas _ retourner false Par exemple nulle nulle 1 l bool bool true false Programmation assist e par filtrage 77 De plus il est possible de nommer la t te ou le reste d une liste argument avec des filtres utilisant let t te function ti r gt t _ gt failwith t te t te a list gt a lt fun gt t te 1 2 3 4l int 1 La clause t r gt t signifie si la liste
66. ces deux op rations se programment facilement On convient d utiliser le registre r 30 comme pointeur de pile La pile commence tout en haut de la m moire et cro t vers le bas Le registre r 30 pointe vers le dernier mot empil Avec ces conventions empiler un registre disons r 31 se traduit par sub r 30 4 r 30 store r 30 0 r 31 L instruction sub alloue de la place pour le registre empiler l instruction store stocke sa valeur l emplacement allou R ciproquement d piler r 31 se traduit par 260 Simulation d un processeur load r 30 0 r 31 add r 30 4 r 30 L instruction load recharge la valeur du registre l instruction add r cup re la place qui lui tait allou e sur la pile Comme exemple d utilisation de la pile voici un sous programme qui calcule la fonction factorielle de la mani re r cursive classique Adr Instruction Commentaire 100 branz r 1 112 si l argument n n est pas nul aller en 112 104 addr 0 1 r 1 mettre la constante 1 dans r 1 108 jmp r 31 r O retour l appelant 112 sub r 30 8 r 30 r server deux mots dans la pile 116 store r 30 4 r 31 empiler r 31 l adresse de retour 120 store r 30 O r 1 et empiler r 1 n 124 subr 1 1 r 1 appel r cursif sur n 1 128 jump 100 r 31 au retour r 1 contient n 1 132 load r 30 O r 2 d pile n mis dans r 2 136 load r 30 4 r 31 d pile l adresse de retour 140 add r 30 8 r 30 r cup re la place en pile
67. compl tement automatique car nous utiliserons le partage toutes les occurrences d une inconnue dans les quations du syst me r soudre seront repr sent es physiquement par le m me objet en m moire Remplacer partout l inconnue par une valeur reviendra simplement modifier le contenu de l objet qui repr sente l inconnue en y d posant la valeur Pratiquement nos variables auront donc deux statuts possibles elles seront soit des inconnues n ayant donc jamais re u de valeur soit des variables connues ayant donc une valeur associ e Par exemple pour le syst me r solu ti int to 3 int ti sera une variable connue valant int t une variable connue valant t3 int tandis 3 que t3 sera toujours une variable inconnue Utilisation des sch mas de types Le polymorphisme est donc mod lis par des sch mas de type Chaque fois qu on doit utiliser un sch ma de type on se contente d utiliser le type qui d crit le sch ma avec de nouvelles inconnues Par exemple si l on veut utiliser le sch ma Pour tout type la la int on utilisera le type ty int o ty est une nouvelle inconnue Le sch ma de type correspond l ensemble de tous les types obtenus en rempla ant a par un type quelconque Une fois a remplac e par une nouvelle inconnue cette inconnue pourra recevoir n importe quelle valeur par la suite Ainsi la fonction d finie par let f x 1 a pour sch ma de type Pour tout type la
68. crivons le code titre d exemple La fonction prend une r f rence c en argument et modifie son contenu c pour y mettre la valeur courante de la r f rence plus un 1 Los let incr mente c c 1 c incr mente int ref gt unit lt fun gt incr mente compteur lcompteur int 4 Les variables imp ratives Un identificateur li une r f rence se comporte comme les variables des langages imp ratifs C Pascal Ada puisqu on peut modifier volont le contenu de la r f rence La seule diff rence est qu en Caml il faut explicitement d r f rencer l identificateur l aide de l op rateur pour en obtenir la valeur courante la distinction entre l objet variable et la valeur courante de cet objet est donc plus nette Comme nous l avions annonc la section 1 3 la d finition d un nom par la con struction let est diff rente de l affectation d une variable Nous sommes maintenant en mesure de comprendre cette diff rence en comparant la red finition d un identificateur par un nouveau let et l affectation d un identificateur li une r f rence Un programme utilisant des r f rences 49 let x 1 let x ref 1 x int 1 x int ref ref 1 let f y x y let f y x y f int gt int lt fun gt f int gt int lt fun gt let x 2 x 2 x int 2 unit f O f 0 int 1 int 2
69. de toute la s quence est rien Cela s explique naturellement parce que le r sultat de la premi re impression un premier rien a t oubli De mani re g n rale la s quence jette le r sultat du premier calcul et renvoie le r sultat du second e1 e2 s value en la m me valeur que e2 Comme le r sultat de e est d truit il est clair que l expression e n est utile que si elle produit des effets il serait stupide d valuer la s quence 1 2 O qui rendrait exactement le m me r sultat que 0 1 2 0 Entr e interactive Attention cette expression est de type int mais est utilis e avec le type unit int 0 On constate d ailleurs que le compilateur met une alerte pour indiquer que l expression 1 2 produit un r sultat qui sera ignor Conventions syntaxiques 15 Pour d limiter pr cis ment une s quence on l encadre souvent entre les mots cl s begin d but et end fin begin print_string Voil print_string Caml print_newline end Voil Caml unit La derni re expression print_newline fait imprimer un retour chariot La fonction print_newline op re enti rement par effets elle n a donc pas de param tre significatif ni de r sultat significatif 1 7 Conventions syntaxiques R sumons quelques conventions syntaxiques qu il est bon d avoir en t te pour la suite D finitions de fonctions Pour les d finitions d
70. e est donc un cas particulier de fonctionnelle puisqu elle per met de cr er d autres fonctions en fixant certains de ses arguments Cette propri t est en fait inscrite dans le type d une fonction curryfi e Par exemple le type de add est int gt int gt int Or le constructeur de type gt associe droite ce qui signifie que le type de add n est autre que int gt int gt int Cette criture explicitement parenth s e indique clairement que add est une fonctionnelle tant donn un entier add retourne une autre fonction dont le type est justement int gt int Cela para t difficile comprendre au premier abord mais c est simplement une autre mani re de voir des phrases aussi simple que ajouter 2 au r sultat pr c dent qui signifie en fait utiliser l addition avec l un des arguments fix 2 et appliquer cette fonction au r sultat pr c dent En Caml cela correspondrait valuer add 2 r sultat pr c dent Une autre approche f conde est de consid rer add comme une fonction g n rique qui permet d obtenir la famille de toutes les fonctions qui ajoutent une constante leur argument et qui sont donc de type int gt int Par exemple la fonction add_3 qui ajoute 3 son argument est d finie par Une fonctionnelle de tri polymorphe 65 let add_3 add 3 add_3 int gt int lt fun gt L application partielle d une fonction curryfi e pour fixer c
71. else x ins re l ment reste ins re a gt a list gt a list lt fun gt Fonctionnelles simples sur les listes 81 G n ralisation du tri tout type d ordre Pour g n raliser la fonction de tri toute sorte d ordres il suffit de passer la fonction de comparaison en argument comme on l a vu au chapitre 4 Les fonctions ins re et tri_par_insertion prennent alors un argument suppl mentaire ordre qu on utilise pour comparer les l ments la place de la comparaison lt let rec ins re ordre l ment function O gt l ment x reste as L gt if ordre l ment x then l ment 1 else x ins re ordre l ment reste ins re a gt a gt bool gt a gt a list gt a list lt fun gt let rec tri_par_insertion ordre function C1 gt x reste gt ins re ordre x tri_par_insertion ordre reste tri_par_insertion a gt a gt bool gt a list gt a list lt fun gt La m me fonction nous permet maintenant de trier indiff remment des listes de cha nes ou de nombres l endroit ou l envers tri_par_insertion function x gt function y gt x lt y 3 1 2 int list 1 2 3 tri_par_insertion function x gt function y gt x gt y 3 1 2 int list 3 2 1 tri_par_insertion function x gt function y gt ge_string x y Salut les copain
72. est de fermer la fen tre de CamlTk terminant ainsi la boucle d interaction mainLoop let rafra chir _ couleur x let r int_of_float scale__get rouge and v int_of_float scale__get vert and b int_of_float scale__get bleu in let couleur printf__sprintf 02x 02x 02x r v b in frame__configure chantillon Background NamedColor couleur La fonction rafra chir_couleur est le c ur du programme elle change la couleur d chantillon pour refl ter l tat courant des trois glissi res Elle lit la valeur num rique courante des trois glissi res l aide de scale__get puis construit le nom CamlTk de la couleur correspondante Ce nom est de la forme rrvvbb o rr vv et bb sont les intensit s de rouge de vert et de bleu exprim es sous forme d un nombre hexad cimal deux chiffres Le nom de la couleur est construit l aide de la fonction sprintf du module printf qui est un puissant outil d impression format e La fonction sprintf prend en argument une cha ne de caract re le format et un certain nombre d entiers ou de cha nes de caract res elle affiche la cha ne de caract res en rempla ant les s quences de la forme plus une lettre par le prochain argument Par exemple sprintf d 44 1 2 renvoie la cha ne 1 2 Les chiffres et la lettre suivant indiquent le type de l argument afficher et le format d affichage utiliser De nombreux formats sont disponibles Dans l
73. finition env d finition corps Bool en b gt Val_bool enne b Nombre n gt Val_nombre n Paire e1 e2 gt Val_paire value env ei value env e2 Nil gt Val_nil Cons ei e2 gt Val_cons value env el value env e2 and value_application env liste_de_cas argument match liste_de_cas with gt raise Erreur chec du filtrage motif expr autres_cas gt try let env_ tendu filtrage argument motif env in value env_ tendu expr with chec_filtrage gt value_application env autres_cas argument and value_d finition env_courant d f match d f r cursive with false gt d f nom value env_courant d f expr env_courant true gt match d f expr with Fonction liste_de_cas gt let fermeture d finition liste_de_cas environnement in let env_ tendu d f nom Val_fermeture fermeture env_courant in fermeture environnement lt env_ tendu env_ tendu _ gt raise Erreur let rec non fonctionnel Il reste un point d licat expliquer la d finition r cursive Nous nous sommes limit s aux cas o l expression d finissante est une fonction ce qui garantit que la d finition r cursive a toujours un sens let rec f function p gt e1 in La valeur que nous associons f est donc une fermeture du corps de la fonction et d un environnement qui est l environnement courant d valuation augment d une liaison pour f En
74. function Vide gt raise File_vide File prio elt Vide Vide gt Vide File prio elt gauche Vide gt gauche File prio elt Vide droite gt droite File prio elt File prio_g elt_g _ _ as gauche File prio_d elt_d as droite gt if prio_g lt prio_d then File prio_g elt_g enl ve_sommet gauche droite else File prio_d elt_d gauche enl ve_sommet droite let extraire function Vide gt raise File_vide File prio elt _ _ as file gt prio elt enl ve_sommet file L ajout d un l ment un arbre binaire croissant suit le m me principe Si le nouvel l ment a une priorit plus haute que la racine la fonction d ajout s appelle r cursivement pour l ajouter au fils gauche ou au fils droit Si le nouvel l ment est moins prioritaire que la racine elle place le nouvel l ment la racine et s appelle r cursivement pour ajouter l ancienne racine dans un des deux fils La fonction s arr te lorsqu elle arrive sur une feuille Voici un exemple d insertion de z avec la priorit 4 o l on choisit d aller une fois gauche puis une fois droite 8 c 6 o Dans la descente r cursive le choix entre fils gauche et fils droit est arbitraire Cepen dant il ne faut pas choisir toujours le fils gauche ou toujours le fils droit apr s plusieurs ajouts larbre obtenu serait tr s d s quilibr avec une longue branche vers la gauche ou vers la droit
75. gation gr ce au th or me gt gt gt P ou non P et Q lt gt P ou Q Th or me pour toutes propositions Q P P ou non P et Q lt gt P ou Q Pour finir un petit exercice le premier exemple s appelle la loi de Pierce gt gt gt P gt Q gt P gt P Th or me pour toutes propositions Q P P gt Q gt P gt P gt gt gt P gt Q gt P gt Q P gt Q gt P gt Q n est pas un th or me car la proposition est fausse quand 228 D monstration de propositions P est vraie Q est fausse gt gt gt P lt gt Q lt gt P ou Q gt P et Q Th or me pour toutes propositions Q P P lt gt Q lt gt P ou Q gt P et Q L auriez vous devin en r fl chissant au sens des connecteurs 12 8 Pour aller plus loin l analyseur lexical universel Dans cette section nous impl mentons l analyseur lexical universel utilis pour lire les propositions On rappelle l interface de ce module Fichier lexuniv mli type lex me MC of string Ident of string Entier of int value construire_analyseur string list gt char stream gt lex me stream L impl mentation reprend de gros morceaux de l analyseur lexical crit pour le mini Logo chapitre 9 section 9 6 en les rendant un peu plus g n raux La principale nouveaut est l introduction de tables de hachage pour d cider rapidement si un iden tificateur
76. gt 320 Recherche de motifs dans un texte let grep_sur_fichier auto nom_fich try let canal open_in nom_fich in try grep_sur_canal auto nom_fich canal close_in canal with exc gt close_ in canal raise exc with sys__Sys_error message gt prerr_string Erreur sur le fichier prerr_string nom_fich prerr_string prerr_endline message La derni re phrase du module grep v rifie que la ligne de commande a la bonne forme compile l expression rationnelle en automate d terministe et applique l automate obtenu sur les fichiers sp cifi s Fichier grep ml if sys__interactive then else if vect_length sys__command_line lt 2 then begin prerr_endline Utilisation grep lt motif gt lt fichiers gt exit 2 end else begin let expr try lire stream_of_ string sys__command_line 1 with Parse_error Parse_failure gt prerr_endline Erreur de syntaxe dans l expression exit 2 in let auto d terminise expr_vers_automate expr in if vect_length sys__command_line gt 3 then for i 2 to vect_length sys__command_line 1 do grep_sur_fichier auto sys__command_line i done else grep_sur_canal auto entr e standard std_in exit if ligne_ trouv e then 0 else 1 end 16 7 Annexe Pour achever le programme grep il reste impl menter le module ensent qui d finit le type abstrait des ensembles d entiers En voici une impl mentation simple base de listes croissantes d
77. gt non phrase gt phrase synonyme_de_phrase string list gt string list lt fun gt La boucle de dialogue Nous en arrivons maintenant au c ur du programme les fonctions qui interpr tent les r ponses de l utilisateur Commen ons par un petit utilitaire pour d terminer si la 142 Le docteur consultation est termin e C est le cas si la phrase tap e est Au revoir ou Salut Rappelons que le caract re est autoris dans les identificateurs ainsi x et x sont des noms utilisables en Caml on peut donc choisir tout naturellement c est_fini let c est_fini ph ph au revoir ph salut l c est_fini string list gt bool lt fun gt Pour r pondre au patient la fonction r pond_au_patient se contente d essayer suc cessivement ses strat gies pr d finies et d crire au terminal la r ponse trouv e Pour cela on commence par passer le texte du patient en minuscules puis on le transforme en une liste de mots qu on appelle phrase Si cette phrase indique la fin de la consul tation on lance l exception Fini Sinon on cherche l ensemble des r ponses possibles pour la phrase donn e en essayant de trouver un associ la phrase ou l un de ses mots dans la base de donn es de Cam lia Lorsque l une de ces tentatives choue elle d clenche forc ment l exception Pas_trouv qui est rattrap e pour essayer la strat gie suivante Finale
78. gt expression gt type_simple and type_d f environnement gt d finition gt environnement exception Erreur of string 346 Un synth tiseur de types L impl mentation du module synthese commence par une fonction auxiliaire de typage des motifs qui sert d terminer le type d une fonction Fichier synthese ml open syntaxe open types let rec type_motif env function Motif_variable id gt let ty nouvelle_inconnue in ty id sch ma_trivial ty env Motif_bool en b gt type_bool env Motif_nombre n gt type_int env Motif_paire m1 m2 gt let ty1 env1 type_motif env m in let ty2 env2 type_motif envi m2 in type_produit ty1 ty2 env2 Motif_nil gt type_liste nouvelle_inconnue env Motif_cons m1 m2 gt let ty1 env1 type_motif env m in let ty2 env2 type_motif envi m2 in unifie type_liste ty1 ty2 ty2 env2 La fonction type_motif renvoie deux r sultats d une part le type du motif c est dire le type des valeurs qu on a le droit de filtrer par ce motif d autre part un environnement de typage tendu associant des inconnues de typage aux variables du motif Par exemple le motif x t a pour type t list o t est une inconnue puisqu en l absence d information sur les utilisations de x et de t on ne sait rien de plus sur le type des listes filtr es par ce motif et on tend l e
79. il semble manquer un certain nombre d instructions indispensables l affectation instruction move certaines comparaisons on a inf rieur mais pas sup rieur l appel de sous programme le retour de sous programme la gestion de la pile Nous allons voir que toutes ces fonctionnalit s s expriment facilement en une ou deux instruc tions de la pico machine Z ro comme argument Beaucoup d op rations utiles s obtiennent en fixant z ro un des deux arguments d une instruction en prenant soit la constante 0 soit le registre r 0 comme argument Voici quelques exemples add r1 0 72 Copie r1 dans r2 instruction move add r O n r2 Met la constante n dans r instruction move sub r 0 r1 r2 Met l oppos de r dans r2 instruction neg braz r 0 a Saute l adresse a load r1 0 r2 Lit le mot l adresse calcul e r load r 0 a r2 Lit le mot l adresse constante a Le registre z ro comme r sultat Parfois le r sultat d une op ration est inutile La mani re standard de s en d barrasser sans modifier aucun registre est de mettre r 0 comme registre de destination Par exemple jmp a r 0 se branche l adresse a sans mettre l adresse de retour dans aucun registre N gation bool enne et inversion de tests En supposant les valeurs de v rit repr sent es par 0 pour faux et autre chose que 0 pour vrai l instruction seq r1 r 0 r2 calcule la n gation d une valeur de v rit si r
80. int and descr_instruction Affectation_var of string expression If of expression instruction instruction Chaque n ud du type instruction dans l arbre de syntaxe abstraite est ainsi annot par un entier le num ro de ligne Nous n avons pas utilis cette technique dans ce chapitre car elle alourdit d sagr ablement toutes les fonctions qui op rent sur l arbre de syntaxe abstraite C est cependant une technique tr s g n rale qui peut servir pour bien d autres types d annotations en plus des num ros de lignes types des expressions informations de compilation informations de mise au point debugging 15 3 Compilation Cette section pr sente un compilateur pour le langage mini Pascal produisant du code pour le pico processeur d crit dans le chapitre 14 Le compilateur se pr sente sous la forme d un module compil dont l interface est fort simple au contraire de l impl mentation 290 Compilation de mini Pascal Fichier compil mli value compile_programme syntaxe__programme gt unit La fonction compile_programme crit directement sur la sortie standard le code assem bleur pour le programme donn en argument Repr sentation des donn es Commen ons par d finir comment les types de donn es mini Pascal sont repr sent s en machine Les entiers type integer sont directement repr sent s par les entiers de la machine Pour les bool ens type boolean nous repr senton
81. int gt se prononce fl che qui est le type des fonctions des entiers int vers les entiers gt int et ce nom a pour valeur une fonction lt fun gt Le syst me a trouv tout seul le type de la fonction mais il ne sait pas comment imprimer les valeurs fonctionnelles parce que leur repr sentation interne est faite de code machine il affiche donc simplement lt fun gt sans plus de pr cisions Effectivement le nom successeur poss de maintenant une valeur successeur int gt int lt fun gt Une d finition de fonction n est donc pas essentiellement diff rente d une d finition d entier ou de cha ne de caract res Elle d finit simplement le nom de la fonction et lui donne une valeur qui est une fonction ce qu on appelle une valeur fonctionnelle Application de fonctions L application d une fonction son argument suit aussi la convention math matique rappelons que f x se prononce f de x successeur 2 int 3 Le langage Caml fournit une syntaxe plus souple pour utiliser et d finir les fonctions on peut supprimer les parenth ses autour des noms des arguments des fonctions aussi bien au cours d une d finition que lors d une application tant donn e la paresse l gendaire des programmeurs c est bien s r cette habitude qui pr domine Avec cette convention on crit simplement let successeur x x 1 successeur int gt int lt fun gt succes
82. int_of_float 195 interactivit 6 181 366 interface homme machine 193 interfaces 221 interfaces de modules 186 188 interpr tation 326 366 interruption 142 invite 6 it rateurs 81 82 92 94 96 105 lecture au clavier 67 141 182 lecture d une r f rence 47 lecture dans un tableau 41 lecture sur fichier 182 Lempel Ziv 253 let 7 8 376 let rec 21 22 lex mes 160 liaisons 7 20 lin aire complexit 32 101 lin arit du filtrage 121 listes 75 78 83 88 130 listes d association 131 134 170 230 logique 207 Logo 147 169 longueur d un tableau 41 42 longueur d une cha ne 24 46 100 longueur d une liste 93 104 mainLoop 194 make_matrix 199 match 84 matrice 199 menus 197 modifications physiques 38 150 163 363 modules 184 monomorphe 57 mot cl 217 motifs ou 163 motifs intervalles 163 mutable 150 n uplets 63 n gation 208 nil 75 noms 7 noms ext rieurs 184 noms qualifi s 184 not 214 occurrence test d 354 of 110 open 184 openTk 194 ou bool en 26 ou bit bit 251 263 ou exclusif 263 ouverts modules 184 ouverture d un canal 182 239 pack 194 paires 63 69 palindromes 25 Index paradoxes 208 param tres de types 58 Pascal 277 peintures 113 phrase Caml 6 pico processeur 255 289 pile du pico processeur 259 291 piles 318 point courant 148 point fixe
83. le registre 0 a une propri t particuli re il contient toujours l entier z ro Autrement dit crire dans ce registre n a aucun effet il garde sa valeur d origine c est dire 0 On peut douter de l utilit d un tel registre contenant toujours la m me information Et pourtant il sert beaucoup il permet de r gulariser et de simplifier le jeu d instructions comme nous le verrons dans les exemples Tout comme le banc de registres la m moire de donn es est elle aussi organis e en mots Comme sur les machines 32 bits modernes les adresses des cases m moire sont multiples de 4 le premier mot est l adresse z ro le deuxi me l adresse 4 etc Enfin la m moire de code contient une instruction par case Les adresses de code sont des entiers tr s r alistement nos instructions sont toutes cod es sur un mot ma chine leurs adresses sont donc aussi multiples de 4 Cependant pour simplifier la simulation nous les rangeons dans un tableau Caml et les repr sentons non pas par un entier mais par une valeur de type somme Ainsi la premi re instruction est l adresse z ro mais rang e dans la case num ro 0 du tableau des instructions la deuxi me in struction est l adresse quatre mais rang e dans la case num ro 1 du tableau des instructions etc Cette division de la m moire en deux zones n est pas courante dans les processeurs En g n ral la m moire est constitu e de mots ou d octet
84. load_object alex zo load_object asynt zo asynt__analyse_phrase alex__analyseur_lexical stream_of_string ve av 15 L utilisation interactive de modules compil s ind pendamment est un peu d licate En particulier il faut charger les fichiers de code compil dans le bon ordre un module doit tre charg avant les modules qui l utilisent Ces points sont expliqu s en d tails dans le chapitre 4 du Manuel de r f rence du langage Caml 11 Interfaces graphiques O Caml attrape des boutons et ouvre les fen tres UMAINS ET MACHINES n interagissent pas uniquement par l interm diaire d un clavier et d un cran de texte Nous montrons dans ce chapitre comment doter les programmes Caml de jolies interfaces homme machine graphiques avec menus boutons barres de d filement etc Nous utiliserons pour cela la biblioth que CamlTk qui fournit une interface simple avec la bo te outils toolkit Tk Les programmes de ce chapitre peuvent tre ex cut s avec camltktop une version du syst me interactif Caml qui int gre la biblioth que CamlTk elle se lance par la commande camllight camltktop 11 1 Structure d une interface graphique Une interface utilisateur r alis e avec CamITk est constitu e d un certain nombre de composants de base en anglais widgets tels que boutons menus zones d entr e de texte etc Le programme cr e les composants dont il a besoin pour interagir avec l utilis
85. lt proposition0 p gt gt p and proposition2 flux lire_op ration function lt MC et gt gt propositioni function p q gt Et p q flux and proposition3 flux lire_op ration function lt MC ou gt gt proposition2 function p q gt Ou p q flux and proposition4 flux lire_op ration function lt MC gt gt gt proposition3 Le v rificateur de tautologies 221 function p q gt Implique p q flux and propositions flux lire_op ration function lt MC lt gt gt gt proposition function p q gt quivalent p q flux Pour construire la fonction principale d analyse syntaxique nous engendrons un analyseur lexical en appliquant partiellement la fonction construire_analyseur la liste des mots cl s puis nous composons cet analyseur lexical avec la fonction lire_proposition Fichier asynt ml let analyseur _lexical construire_analyseur vrai faux MES nys non et ou nasi n lt gt let analyse_proposition cha ne lire_proposition analyseur_lexical stream_of_string cha ne Pour finir nous cachons toutes les fonctions interm diaires d analyse syntaxique en exportant uniquement la fonction principale Fichier asynt mli open prop value analyse_proposition string gt proposition 12 6 Le v rificateur de tautologies Tout est pr t pour r aliser un d monstrat
86. lt fun gt Dans cette situation il faut vous efforcer de boucher les trous de votre filtrage Laisser des filtrages non exhaustifs dans un programme est g n ralement consid r comme un laisser aller de mauvais aloi 6 8 Structures de donn es et r currence Cette section peut tre saut e en premi re lecture Nous y tendons le principe de r currence aux types de donn es Comme pour les listes nous aimerions disposer d un moyen de prouver des pro pri t s sur les programmes qui utilisent des types somme ou des types produit Comme Structures de donn es et r currence 123 dans le cas des listes il suffit de trouver un nombre li aux donn es sur lequel on puisse employer le principe de r currence Pour les listes nous avions utilis la longueur En fait il suffit pour g n raliser tous les types somme de remarquer que la longueur d une liste n est autre que le nombre d utilisation du constructeur n cessaire la construction de la liste Pour un type somme g n ral on pourra ainsi raisonner sur le nombre d occurrences des constructeurs du type Le cas particulier de la liste vide sera transpos tous les constructeurs constants du type tandis que le cas de correspondra au nombre d occurrences des constructeurs non constants Pour les types produit il y a plusieurs mani res d tendre le raisonnement par r currence Pour simplifier supposons que nous devions d montrer une pr
87. me exige moins de calculs lorsqu il est crit en style imp ratif que lorsqu il est crit en style fonc tionnel Enfin certains algorithmes s expriment naturellement en termes d volution d un tat la programmation imp rative s impose alors Nous avons pour l instant illustr les effets d entr es sorties plus pr cis ment les impressions Nous allons maintenant faire des effets sur la m moire ce qu on appelle aussi des modifications physiques ou modifications en place de donn es Pour cela il nous faut disposer de cases m moire modifiables par le programme Caml propose pour cela les notions de r f rences et de tableaux Nous commen ons par tudier les tableaux qui sont plus simples Puisque la notion de temps intervient en programmation imp rative il nous faut un moyen de sp cifier au langage fait ceci d abord et fait cela ensuite c est la notion de s quence que nous avons d j vue au chapitre 1 Nous avons galement besoin de r p ter des suites d effets c est la notion de boucles Nous d crivons ces construction puis appliquons ces outils au calcul sur les polyn mes Boucles 39 3 2 Boucles Caml fournit deux sortes de boucles pour r p ter des effets la boucle pour et la boucle tant que La boucle pour r p te un calcul un nombre de fois fix l avance la boucle tant que r p te un calcul tant qu une condition reste vraie Boucle tant que Bouc
88. me celle d tre une liste Vous aurez aussi remarqu que le caract re s est imprim avant l entier 1 les l ments d une liste sont valu s dans un ordre non sp cifi par le langage Dans le cas pr sent le compilateur a choisi l ordre droite gauche ce qui ne convient pas du tout Il va sans dire que vos programmes ne doivent pas reposer sur l ordre d valuation que choisit aujourd hui le compilateur de votre machine la prochaine version du compilateur pourrait bien en choisir un autre Il ne faut donc pas faire d effets pendant la construction d une donn e Cette solution na ve ne marche donc pas du tout Pour obtenir l effet d sir il nous faudrait retarder l valuation de la liste d ordres par exemple en passant une fonction en argument au lieu d une liste let r p te n liste_d ordres for i 1 to n do liste_d ordres done r p te int gt unit gt a gt unit lt fun gt r p te 4 function gt print_int 1 print char 1x1 x1 1 x unit Le r sultat voulu est atteint mais l utilisation de r p te devient extr mement lourde tr s informatique disons Conclusion pour d passer ce probl me il faut prendre du recul c est dire ma nipuler les ordres graphiques non plus comme des fonctions de Caml mais comme des donn es Nous pourrons ainsi en ma triser compl tement l valuation Nous d finirons donc le type ordre des
89. parano aque Que pensez vous de la vie en g n ral Avec une probabilit de 92 37234 let r ponses_types perversion polymorphe I C est moi qui pose les questions Vous souffrez d une schizophr nie en rapide Je ne suis pas l pour r pondre vos volution DANGER questions D apr s mes calculs votre sant mentale est Question tr s int ressante mais qu en compromise pensez vous Mon ultime conseil il ne faut pas rester Quelle question comme cela soignez vous Pourquoi me posez vous cette question let relances Vous le savez tr s bien Parlez moi un peu de vous La r ponse est sans importance tes vous mari Vous le dire ne vous apporterait rien Avez vous des enfants Un psychanalyste n a pas le droit de Parlons de votre entourage r pondre ce genre de questions Aimez vous la vie Je n ai pas le droit de vous r pondre Aimez vous ce moyen de communiquer Il m est interdit de vous le dire Parlons de votre famille Vous ne comprendriez pas Parlez moi encore de vous Permettez moi de ne pas r pondre Que pensez vous des ordinateurs Laissez moi r fl chir Pouvez vous Que pensez vous de Linux reformuler la question Que pensez vous de Caml Je ne suis pas certaine de bien comprendre De quoi parlerons nous maintenant la question Avez vous beaucoup d amis Je ne sai
90. part nom_arriv e let disque_d plac sommet ltige_d part in tige_d part enl ve_sommet ltige_d part tige_arriv e ajoute_disque disque_d plac tige_arriv e d place string int a list ref gt string int a list ref gt unit lt fun gt La mod lisation de l tat initial du jeu n cessite la d finition d une tige vide et d une tige pleine en fonction du nombre de disques utilis s let tige_vide nombre_de_disques nombre_de_disques tige_vide a gt a b list lt fun gt let tige_pleine nombre_de_disques let rec liste_des_ disques i if i lt nombre_de_disques then i liste des disques i 1 else in 0 liste_des_ disques 1 tige_pleine int gt int int list lt fun gt Nous d finissons maintenant une proc dure de r solution compl te incluant les fonc tions d impression Nous maintenons l tat des trois tiges l aide de trois r f rences gauche milieu et droite Remarquez que la proc dure r cursive locale hanoi prend ces trois r f rences en argument et qu elles sont modifi es physiquement par la proc dure d place let jeu nombre_de_disques let gauche ref tige_pleine nombre_de_disques and milieu ref tige_vide nombre_de_disques and droite ref tige_vide nombre_de_disques in let rec hanoi hauteur d part interm diaire destination if hauteur gt 0 then begin hanoi hauteur 1 d par
91. puisqu elle est quivalente l application d une fonction anonyme Nous comprenons mieux maintenant le typage des phrases quivalentes suivantes function y gt y y function x gt x Entr e interactive gt function y gt y y function x gt x 5 a Cette expression est de type a gt b mais est utilis e avec le type a let y function x gt x in y y _a gt _a lt fun gt match function x gt x with y gt y y Entr e interactive gt match function x gt x with y gt gt y y 3 A Cette expression est de type a gt b mais est utilis e avec le type a 18 2 L algorithme de synth se de types Nous programmons maintenant l algorithme de synth se de types proprement dit la partie du synth tiseur qui examine le programme et produit les quations entre types qui d terminent les types de tous les objets du programme Nous verrons plus tard com ment ces quations sont r solues et comment les expressions de types sont repr sent es de mani re manipuler efficacement les quations entre types Pour l instant nous nous contentons de donner l interface du module types qui d finit deux types de donn es abstraits type_simple et sch ma_de_types ainsi que toutes les op rations sur ces types dont nous avons besoin Fichier types mli type type_simple and sch ma_de_types value type_int type_simple and type_bool type_simple and
92. rations primitives testent alors si leurs arguments sont d j calcul s ou non S ils ne le sont pas elles les d g lent Tout comme le langage Caml notre valuateur fonctionne donc en appel par valeur mais sa transformation en valuateur par nom n est pas tr s difficile Les d finitions r cursives Vous aurez remarqu que nous limitons la d finition de valeurs r cursives aux fonc tions imm diates c est dire directement introduites par le mot cl function Ce point est raisonnable mais discutable car on peut donner un sens des d finitions de valeurs non fonctionnelles L cueil est de pr tendre donner aussi un sens des d finitions qui n en ont pas par exemple let rec x x 1 Pour aller plus loin 335 En fait une d finition r cursive se ram ne toujours la recherche du point fixe d une certaine fonction En effet toute d finition r cursive est de la forme let rec x phi x ce qui signifie donc que la valeur de x est un point fixe de la fonction phi Par exemple pour la d finition de la fonction factorielle Let rec fact function x gt if x 0 then 1 else x fact x 1 la fonction phi correspondante est function f gt function x gt if x 0 then 1 else x f x 1 En effet phi fact vaut exactement fact On montre que la d finition de fonctions s impl mente correctement dans un langage en appel par valeur En revanche pour les autres valeurs la classe des d finitions
93. res D autre part nous aurons besoin aussi d introduire le m canisme d exceptions de Caml En effet le c ur du programme consiste essayer 126 Le docteur successivement les diff rentes strat gies possibles jusqu ce que l une d entre elles r ussisse Nous verrons que c est justement un emploi typique des exceptions 7 2 Les exceptions Erreurs et rattrapage d erreurs Dans les langages fonctionnels toute fonction qui ne boucle pas ind finiment doit rendre une valeur quel que soit son argument Malheureusement certaines fonctions bien que n cessairement d finies pour toute valeur de leur type argument ne peuvent pas retourner de valeur sens e pour tous les arguments possibles Consid rez par ex emple la division entre nombres entiers que doit elle faire lorsqu on tente de diviser par 0 Le probl me se pose aussi pour les donn es structur es consid rez la fonction t te qui renvoie la t te d une liste Que peut elle faire lorsque son argument est la liste vide Dans de telles situations la fonction doit chouer c est dire arr ter les calculs et signaler une erreur C est ce que nous avons fait en utilisant la fonction pr d finie failwith failwith string gt a lt fun gt qui envoie un message indiquant la cause de l chec C est pourquoi nous d finissons t te par let t te function 1 gt failwith t te x _ gt x t te a list gt a
94. res cl lt f lire_expr r gt gt t lt f c gt gt Caract res c lt stream_check function c gt c lt gt amp amp c lt gt amp amp c lt gt c gt gt Caract res c and lire_classe function lt lire_ensemble cl gt gt subtract tous_car cl lt lire_ensemble cl gt gt cl and lire_ensemble function e gt gt f lt lire_car c1 lire_intervalle c1 c2 gt gt c2 and lire_intervalle c1 function Les automates 309 lt f lire_car c2 lire_ensemble reste gt gt union intervalle ci c2 reste lt lire_ensemble reste gt gt union c1 reste and lire_car function KAAN ce gt gt c g c gt gt c Nous avons d introduire les fonctions interm diaires lire_alternative lire_fin_s q etc pour tenir compte du caract re enti rement d terministe du filtrage sur les flux Pour lire_expr par exemple il aurait t plus naturel d crire let rec lire_expr function lt lire_s q r1 lire_expr r2 gt gt Alternative r1 r2 lt lire_s q ri gt gt r1 Cette criture ne donne pas le r sultat attendu si Lire_s q reconna t le d but du flux on s engage de mani re d finitive dans le premier cas du filtrage Si le prochain caract re du flux n est pas une barre verticale le syst me d clenche une erreur de syntaxe mais ne se rab
95. rifie _type la condition de WHILE Boolean type_expr env condition type_instr env corps Write expr gt v rifie_type l argument de WRITE Integer type_expr env expr Read nom_ var gt v rifie_type l argument de READ Integer cherche_variable nom_var env Bloc liste gt do_list type_instr env liste Typage d un programme Les fonctions de typage d une d claration de fonction ou de proc dure ajoutent dans l environnement les types d clar s pour les param tres et les variables locales puis v rifient dans cet environnement le typage du corps de la fonction ou de la proc dure Fichier typage ml let ajoute_var nom typ env ajoute_variable nom typ env let type_proc dure env_global nom d cl let env list_it ajoute_var d cl proc_variables d cl proc_param tres env_global in type_instr env d cl proc_corps 288 Compilation de mini Pascal let type_fonction env_global nom d cl v rifie_non_tableau passage comme r sultat de la fonction d cl fonc_type_r sultat let env list_it ajoute_var nom d cl fonc_type_ r sultat d cl fonc_ variables d cl fonc_ param tres env_global in type_instr env d cl fonc_corps 7 nom Enfin le typage d un programme tout entier consiste construire un environnement de typage global correspondant aux d clarations de variables globales de fonctions et de proc dures puis v rifier les types dan
96. s Quand faut il se contenter d engranger des quations et quel moment faut il d cider d entrer dans la phase de r solution Une premi re r ponse simple serait il faut r soudre en fin de phrase C est exact mais insuffisant En effet lorsqu on crit en Caml let identit x x in identit 1 identit oui il faut d cider quel est le type de identit avant de typer la partie in En effet si et c est le cas ici le nom d fini par let poss de un type polymorphe dont certaines variables restent des inconnues il faut les d tecter tout de suite pour pouvoir em ployer ce nom avec diff rents types dans la partie in C est cette r solution partielle de l ensemble des quations de typage qui rend la synth se de type difficile Il nous faudra donc r soudre les contraintes avant de typer la partie in d une expres sion let Plus pr cis ment il nous faudra seulement d couvrir le type de l identificateur d fini au cas o ce type comporterait des param tres et serait donc polymorphe Ici intervient un ph nom ne que nous admettrons nous contentant de le justifier intuitive ment seules les inconnues introduites pendant le typage de la d finition sont suscepti bles de devenir des param tres du type de l identificateur d fini Les autres inconnues celles qui apparaissaient dans le syst me avant le typage de la d finition ne doivent pas devenir des param tres car elles peuvent intervenir pl
97. sultats partiels de la fonction lors des appels r cursifs Cela conduit crire une fonction elle aussi plus g n rale dans la mesure o il est possible maintenant de l appeler avec un accumulateur non vide au d part Prenant un peu de recul on d finit donc une fonction auxiliaire concat ne_ _l envers qui tant donn s une liste et un accumulateur recopie la liste en t te de l accumulateur let rec concat ne l envers accu function gt accu x l1 gt concat ne_ _l envers x accu 1l concat ne_ _l envers a list gt a list gt a list lt fun gt Listes et r currence 103 concat ne_ _l envers 0 1 2 3 int list 3 2 1 0 Illustrons graphiquement le comportement de cette fonction On part d une liste 1 et d un accumulateur accu qui contient ventuellement d j des l ments 1 accu TR hr JON JON 2 PAN SE 3 Puis on recopie la t te de la liste 1 dans l accumulateur obtenant reste 1l accu k FR JON 3 T 4 l tape suivante on aura reste reste 1 aceu z ti 2 J 2 1 ZX 2 77N Il est clair maintenant que l accumulateur engrange les l ments de la liste 1 l envers La fonction rev s en d duit simplement en appelant concat ne_ _l envers avec un accumulateur vide let rev 1 concat ne _l envers 1l rev a list gt a list lt fun gt rev 1 2 3 l
98. t on utilise l op ration de modification physique d un champ d enregistrement not e e tiquette lt e2 o e1 et e2 sont deux expressions et tiquette le nom d une tiquette d enregistrement L ex cution de cette expression remplace le contenu du champ tiquette de l enregistrement e par la valeur de l expression e2 Comme toute modifi cation physique cette expression renvoie la valeur rien La fonction d p t s crit donc simplement let d p t compte montant compte solde lt montant compte solde d p t compte gt float gt unit lt fun gt d p t compte_de_durand 30 0 unit compte_de_durand solde float 1030 0 Variables r manentes Cet exemple nous permet aussi d aborder les r f rences locales aux fonctions qui conservent leur valeur entre les diff rents appel la fonction Nous d finissons la fonc tion de cr ation des comptes elle doit n cessairement allouer un nouveau num ro chaque nouveau compte cr Pour cela il lui suffit de tenir jour une r f rence enti re contenant le dernier num ro de compte attribu et de l incr menter chaque cr ation Pour s assurer que cette r f rence ne peut tre modifi e par inadvertance dans une autre partie du programme de gestion des comptes on la rend compl tement locale au corps de la fonction qui cr e les comptes let cr e_compte let num ro_de_compte ref O in function d pot
99. termine ce num ro s appelle justement la fonction de hachage En termes savants on dit qu on partitionne les cl s en classes d quivalence modulo la fonction de hachage En termes simples on range les cl s dans le m me sous ensemble quand elles ont la m me image par la fonction de hachage Prenons un exemple tr s simple supposons que les cl s soient des nombres entiers Comment partager rapide ment ces entiers en dix sous ensembles Il suffit de regarder leur dernier chiffre Si l on veut les partager en deux sous ensembles on consid re leur parit pair ou impair De fa on g n rale une mani re de les partager en n sous ensembles est de calculer le reste de leur division par n titre d monstratif nous prenons dix sous ensembles Notre fonction de hachage est donc let hache cl cl mod 10 Pour aller encore plus loin le hachage 233 hache int gt int lt fun gt Maintenant nous voulons associer des informations nos entiers par exemple des cha nes de caract res C est notamment le cas si nous voulons repr senter un annuaire l envers partir d un num ro de t l phone nous d sirons retrouver le nom du correspondant Sous forme de liste d association cela donne let liste_d association 11 police 16 pompiers 0139635511 standard 0139635198 Pierre 0139635202 Xavier 7234864 Xavier 0139635570 Nelly 3613 T l tel 1 3615 T l tel 3 So
100. un entier et l extraction d un l ment ayant la priorit la plus faible L op ration d extraction renvoie en plus de l l ment extrait la priorit de cet l ment et la file d attente priv e de cet l ment Elle d clenche l exception File_vide si on l applique la file vide On donne en annexe de ce chapitre section 13 4 deux impl mentations possibles du module fileprio partir de l arbre de Huffman renvoy par la fonction construire_arbre on calcule une table de codage adapt e la fonction encode comme suit 246 Compression de fichiers Fichier huffman ml let arbre_vers_codage arbre let codage caract re make_vect 256 fin in let rec remplir_codage pr fixe function Lettre c gt codage caract re int_of_char c lt rev pr fixe Fin gt codage fin lt rev pr fixe Noeud arbre1 arbre2 gt remplir_codage 0 pr fixe arbre1 remplir_codage 1 pr fixe arbre2 in remplir_codage arbre codage La fonction locale remplir_codage effectue une exploration exhaustive de l arbre Son argument pr fixe contient le chemin invers de la racine jusqu au n ud courant Lorsqu on atteint une feuille on remet le chemin l endroit et on le stocke dans la case correspondante du codage Compression et d compression de fichiers Il est temps de recoller tous les morceaux pour d finir les fonctions de compression et de d compression d un fichier Le
101. x somme l somme int list gt int lt fun gt On calcule le produit des l ments d une liste de fa on similaire let rec produit function ET gt 1 x 1 gt x produit 1l produit int list gt int lt fun gt Ces deux derni res fonctions sont des exemples repr sentatifs les fonctions sur les listes sont le plus souvent r cursives et op rent un filtrage sur la liste argument 78 Listes G n ralement la fonction s arr te quand elle rencontre une liste vide et s appelle r cursivement quand la liste n est pas vide Le squelette g n ral d une telle fonction est donc let rec f function 1 gt valeur de base Mcg Les is PC Lis Cela vous explique pourquoi les fonctions nulle t te et reste ne sont gu re employ es en Caml quoi bon tester explicitement if nulle 1 then else quand le filtrage permet de le faire bien plus l gamment En effet en n employant pas le filtrage le squelette g n ral d une fonction r cursive sur les listes s crirait bien plus lourdement let rec f 1 if nulle 1 then valeur de base else let x t te l and 1 reste 1 in f 1 Le mod le g n ral de fonction r cursive d finie par filtrage sur les listes est rapprocher de celui qu on a vu sur les entiers let rec f function O gt solution simple l a a n ETD EE Sch matiquement le squelette le plus g n ral de fonctions r
102. 0 td 10 Td Entier 10 tourne 10 0 l ve_crayon Lc fixe_crayon true lc Lc fixe_crayon true baisse_crayon Bc fixe_crayon false bc Bc fixe_crayon false vide_ cran Ve vide_ cran ve Ve vide_ cran Pour la r p tition des ordres nous avons besoin des suites d ordres s par s par des blancs et plac s entre crochets et comme pour les listes de Caml Syntaxe concr te Syntaxe abstraite S mantique signification Ordres entre crochets Liste d ordres Ex cution des ordres de la liste av 30 td 90 Av Entier 30 Td Entier 90 It ration avec do_list de la fonction ex cute_ordre R p tition d ordres Ordre Rep Une boucle for de Caml r p te 3 av 30 td 90 Rep 3 Av Entier 30 Td Entier 90 Une boucle for qui ex cute trois fois la liste des ordres rep 3 av 30 td 90 Rep 3 Av Entier 30 Td Entier 90 Une boucle for qui ex cute trois fois la liste des ordres 9 5 Notions d analyses syntaxique et lexicale L analyse syntaxique est un probl me difficile Elle correspond l analyse grammat icale de la langue fran aise que vous devez d j avoir appris redouter Cependant lorsqu un tre humain analyse une phrase fran aise une tape extr mement simple et intuitive est pass e sous silence tellement elle va de soi la s paration de la phrase en mots C est cependant une phase non tr
103. 129 172 215 334 exn 127 128 exponentielle complexit 32 360 expressions 168 expressions rationnelles 305 extensionnalit 52 factorielle 20 49 268 275 factorisation gauche 309 false 13 fermeture d un canal 182 fermetures 327 329 334 369 Fibonacci 33 277 303 fichiers 182 file d attente 245 247 filtrage 28 76 78 84 85 110 117 120 126 128 158 162 165 328 filtrage exhaustif 122 filtrage partiel 122 filtres ou 135 fin de fichier 182 fin de phrase 6 fl che type fonctionnel 9 float_of_string 196 flocon 147 154 flottants nombres 34 149 flux 161 165 183 fonctionnelle programmation 37 268 fonctionnelles 59 61 64 66 70 72 73 81 220 279 fonctionnelles sur les listes 81 91 94 96 379 fonctions 8 10 67 68 342 fonctions anonymes 11 68 343 fonctions calcul es 60 for 39 fractales 147 function 11 g n ralisation 345 356 gardes dans les filtres 121 GC 367 glissi re 194 graphisme 148 hachage 229 Hanoi les tours de 28 88 heaps 248 Huffman 240 identificateurs 7 identit 58 62 if 12 imp rative programmation 38 101 268 impl mentations de modules 187 implication 210 implose 92 99 101 impression l cran 22 39 67 140 182 impression format e 195 196 293 in 8 incr mentation 48 inf rence de types 6 61 339 instructions du pico processeur 256
104. 245 Index commandes 38 commentaires 10 229 compilateur ind pendant 6 180 compilation 181 186 188 190 222 289 366 complexit 31 33 35 81 98 composition de fonctions 70 96 compression 237 241 compteur 47 48 54 concat nation de cha nes 8 68 88 100 concat nation de listes 84 92 97 102 conditionnelle 12 26 43 84 configure 195 conjonction 26 209 connecteurs propositionnels 208 cons 75 constructeurs de listes 75 constructeurs de types 63 constructeurs de valeurs 110 116 contrainte de type 11 62 contraintes de type 11 conventions syntaxiques 15 cosinus 150 couleur de trac 152 crayon 149 155 curryfication 64 72 d calage logique 251 252 263 d clarations 187 d clenchement d exceptions 127 172 d compression 242 d finition 9 d finition par cas 28 d finitions 6 8 20 d r f rencement 47 d terminisation 313 diagrammes syntaxiques 17 39 42 84 129 disjonction 26 209 do 39 done 39 downto 39 effacement d un fichier 239 effet 13 37 53 54 else 12 end 14 enregistrements 116 150 ensembles 316 320 entr e standard 183 entr es sorties 181 238 334 entr es sorties structur es 246 265 274 environnements d valuation 170 172 329 environnements de typage 284 erreurs 126 Ershov 295 et bool en 26 et bit bit 252 263 exception 128 exceptions 77 126 127
105. 334 polymorphisme 57 66 70 71 76 81 340 342 368 polyn mes 40 42 43 45 83 85 109 111 port e dynamique 20 177 328 port e statique 20 177 327 positionnement dans un fichier 246 prefix 95 print_char 24 printf 293 priorit file d attente avec 245 247 priorit s 218 281 308 proc dures 14 38 168 produit types 63 116 programmes ind pendants 180 prompt 6 propositions 208 213 quadratique complexit 32 81 101 102 r cup ration d exceptions 126 128 142 172 r cup ration de m moire 367 r currence 32 33 36 103 122 r cursifs types 114 r cursion 19 22 27 28 30 32 77 154 175 177 330 334 348 r f rences 47 90 101 119 230 r gle n 52 54 55 95 363 random 201 rec 22 records 116 red finition 48 ref 47 registres allocation de 294 298 registres du pico processeur 256 regular expressions 305 remplissage de rectangles 152 retard de l valuation 55 157 retournement d une liste 101 rien valeur 14 RISC 255 258 s quence 14 17 53 81 sch mas de types 340 341 simulateur du pico processeur 260 sinus 150 sommation d une formule 61 somme types 110 116 sortie d erreur 183 sortie standard 183 sous cha ne 26 134 240 sous programmes 259 sp cialisation 59 62 67 345 357 spirales 175 sprintf 195 196 stack frame 291 streams 161 suspensions 334
106. 365 367 373 Avant propos On prononce Caml avec le ca de caf et le mel de melba AML est un langage de programmation de conception r cente qui r ussit tre la fois tr s puissant et cependant simple comprendre Issu d une longue r flexion sur les langages de programmation Caml s organise autour d un petit nombre de notions de base chacune facile comprendre et dont la combinaison se r v le extr mement f conde La simplicit et la rigueur de Caml lui valent une popularit grandissante dans l enseignement de l informatique en particulier comme premier lan gage dans des cours d initiation la programmation Son expressivit et sa puissance en font un langage de choix dans les laboratoires de recherche o il a t utilis pour traiter des probl mes parmi les plus ardus de l informatique d monstration assist e par ordinateur analyses automatique de programmes syst mes de r criture compila tion et m tacompilation En bref Caml est un langage facile avec lequel on r sout des probl mes difficiles Longtemps r serv de grosses machines co teuses le langage Caml est main tenant disponible gratuitement sur toute une gamme de machines du micro ordinateur personnel PC Macintosh aux stations de travail les plus puissantes ce qui le rend accessible un vaste public de l amateur curieux au professionnel chevronn en passant par l tudiant informaticien ce vaste
107. Caml va parcourir les mon mes des deux polyn mes deux deux en les multipliant et en enregistrant le produit de leurs coefficients dans le mon me de degr correspondant du produit Pour les fanatiques des formules ceci se traduit par la d finition math matique suivante m n Le produit des deux polyn mes P 5 pi X et Q 5 qj X i 0 j 0 m n est le polyn me P x Q 5 re XF avec rx 5 Pi X qj k 0 i j k m n k ou de fa on quivalente P x Q 5 5 Pi X a DAS k 0 i 0 Remarquez que ces formules d apparence r barbative ne font que r sumer de fa on tr s succinte notre explication en fran ais mais en aucun cas ne la rendent inutile Pour coder la multiplication des polyn mes en Caml le plus difficile est de cal culer la longueur du tableau r sultat On sait cependant que le mon me de plus haut degr du r sultat a pour degr la somme des degr s des mon mes de plus haut degr des polyn mes multipli s Or le degr du mon me de plus haut degr d un polyn me repr sent par un tableau v de longueur l est l 1 C est donc en Caml vect_length v 1 Par exemple le polyn me p x 2x 3 est repr sent par un tableau trois cases et son mon me de plus haut degr est de degr 2 Mais le mon me de degr maximum du produit des polyn mes p et q a pour degr la somme des degr s des mon mes de degr maximum de p et q soit vect_length p 1 vect_length q 1 On en d duit fac
108. G n ralisation tout type d ordre Pour rendre cette proc dure polymorphe encore plus g n rale il suffit de remarquer que c est l emploi de la primitive lt pour comparer les l ments du tableau qui impose le rangement par ordre croissant Il suffit donc de passer la fonction de comparaison en argument pour trier selon toute sorte d ordres Lorsqu on passe ainsi en argument une fonction utilis e dans le corps d une d finition on dit qu on abstrait la fonction Dans le cas du tri on abstrait donc la comparaison et la fonction tri prend alors un argument suppl mentaire ordre une fonction deux arguments x et y renvoyant true si x est inf rieur ou gal y et false sinon ces fonctions sont appel es pr dicats let tri ordre t for i 0 to vect_length t 2 do let min ref i in for j i 1 to vect_length t 1 do if ordre t j t min then min j done change t i min done tri a gt a gt bool gt a vect gt unit lt fun gt Trions par ordre croissant ou d croissant un tableau d entiers en changeant simplement l ordre let t 13 1 2 in tri function x gt function y gt x lt y t t int vect l1 2 31 let t 13 1 21 in tri function x gt function y gt x gt y t t int vect 13 2 11 Ce n est pas plus difficile pour les tableaux de cha nes de caract res en utilisant les fonctions pr d finies de comparaison g
109. L allocation consiste r server un certain espace dans la m moire un bloc de m moire pour y ranger des donn es On l utilise par exemple pour fabriquer des tableaux des paires des cellules de listes ou des cha nes de caract res Un programme Caml ordinaire alloue un grand nombre de blocs mais ces blocs ont g n ralement une dur e de vie assez br ve Un exemple simple lorsqu on utilise des listes il est courant de cr er une liste pour y appliquer aussit t map en ce cas la liste de d part est devenue inutile car seule la liste r sultat est utilis e dans le reste du programme Cela signifie qu on remplit facilement toute la m moire avec des blocs dont beaucoup ne servent plus Pour viter cela il faut savoir lib rer les blocs m moire devenus inutiles pour pouvoir r utiliser la place m moire qu ils occupaient R cup ration de m moire Il y a principalement deux moyens de lib rer des blocs le premier consiste simplement laisser ce soin au programmeur qui devra explicite ment signaler quand un bloc allou est libre Le second est la lib ration implicite g r e automatiquement par un programme sp cialis le r cup rateur de m moire La lib ration explicite n existe pas en Caml car c est une source d erreurs subtiles et fr quentes Fr quentes parce qu il est facile d oublier qu une partie d une structure de donn es est utilis e par la suite et donc de lib rer trop t t cette structure Su
110. Lisp et signifie application multiple La fonction s crit tr s simplement si la liste argument est vide le r sultat est la liste vide Sinon la liste argument est de la forme x 1 et il suffit de mettre en t te du r sultat l application de f x le reste du r sultat tant fourni par un appel r cursif map let rec map f function g gt Sel x 1 gt f x map f l map a gt b gt a list gt b list lt fun gt Cette fois ci le type d arriv e de la fonction f n est plus ignor il doit tre identique au type des l ments de la liste des r sultats map succ 1 2 3 int list 2 3 4 Les polyn mes creux 83 map string_length Bonjour tout le monde int list 7 4 3 6 Nous allons utiliser nos nouvelles connaissances sur les listes pour calculer des polyn mes qui nous taient pr c demment inaccessibles 5 5 Les polyn mes creux Une repr sentation affin e Notre premier programme de manipulation des polyn mes section 3 3 repr sentait les polyn mes par des tableaux d entiers Cette repr sentation est tr s dispendieuse quand les polyn mes ont peu de mon mes dont les degr s sont tr s diff rents il serait insupportable de repr senter le polyn me 1 x10000 par un tableau 10001 cases dont 9999 comporteraient des z ros Les polyn mes ayant cette propri t d avoir une forte proportion de coefficients nuls sont
111. Pascal lire_reste reste gt gt elt reste lt gt gt in function lt lire_ l ment elt lire_reste reste gt gt elt reste lt gt gt La fonctionnelle lire_liste prend en argument un analyseur lire_ l ment et une cha ne s parateur et renvoie un analyseur qui reconna t les listes d l ments reconnus par lire_ l ments s par s par des occurrences de la cha ne s parateur Par exemple lire_liste function lt Entier n gt gt n est une fonction de type lex me stream gt int list qui reconna t les listes d entiers s par s par des virgules En appliquant cette fonction au flux lt Entier 1 MC Entier 2 gt on obtient la liste 1 2 La fonction stream_check employ e dans lire_reste permet de filtrer les car act res qui v rifient une certaine condition De mani re g n rale un motif de la forme lt stream_check p c gt est s lectionn si la fonction p appliqu e au premier l ment du flux renvoie true Le premier l ment du flux est alors li la variable c et le filtrage continue comme d habitude Dans le cas de lire_reste le motif lt stream_check function lex me gt lex me MC s parateur s p gt filtre donc les mots cl s dont le texte est identique la cha ne s parateur L autre fonctionnelle sert analyser les applications d op rateurs binaires infixes comme ou and Fichier syntaxe ml let
112. Puis nous d finissons une autre fonction g qui appelle f avec la variable d j d finie compteur Nous prenons galement bien soin de suivre l volution du contenu de la r f rence compteur compteur int 4 Effets et valuation 55 let g y f compteur y g int gt int lt fun gt compteur int 4 On constate que la d finition de g n a pas modifi la valeur de compteur ce qui semble normal En revanche chaque fois qu on appelle la fonction g avec une valeur v on value l expression f compteur v si bien que la valeur de compteur est incr ment e chaque appel de g ce qui semble toujours un comportement raisonnable g 0 int 1 compteur int 5 Mais supposez maintenant que nous utilisions la r gle n pour simplifier la d finition de g en supprimant l argument y C est bien s r interdit car nous utiliserions la r gle avec l expression f compteur qui n est pas une fonction c est une application et qui de surcro t produit des effets Pour montrer que le comportement du programme changerait faisons le tout de m me en suivant toujours soigneusement l volution de la valeur de compteur let g f compteur g int gt int lt fun gt compteur int 6 On constate que la valeur de compteur a t modifi e en d finissant g En effet pour d finir g on applique maintenant f compteur et cela produit tout naturellement
113. a gt b gt a list gt b list lt fun gt Lors de l appel r cursif map f 1 il faut sauvegarder quelque part la valeur de f x pour l ajouter en t te du r sultat de map f 1 G n ralement ce r sultat interm diaire est sauvegard dans un tableau en attendant le retour de l appel r cursif Ce tableau est appel pile d ex cution du programme Comme toutes les ressources m moire la pile est de taille finie et une fonction qui travaille en espace de pile constant comme do_list est pr f rable une fonction qui consomme de la pile comme map Lorsqu on a le choix entre une fonction r cursive terminale et une autre qui ne l est pas on pr f re g n ralement celle qui est r cursive terminale pourvu qu elle reste simple rendre une r cursion terminale ne justifie g n ralement pas qu on complique le programme It rateurs et effets L it rateur list_it est tr s puissant en ce qui concerne les calculs proprement dits il n est pas n cessaire d en avoir d autre Par exemple map s crit tr s facilement avec list_it let map f 1 list_it function x gt function res gt f x res 1 l map a gt b gt a list gt b list lt fun gt 106 Listes map successeur 1 2 3 int list 2 3 4 Dans le m me esprit il serait tentant d crire do_list en fonction de list_it let do_list f 1 list_it function x gt function y gt f x y 1 do_
114. amp not x gt 2 c est dire x gt 1 amp amp x lt 2 Il faut savoir que le contraire de lt est gt celui de gt est lt et r ciproquement Remarquez que nous pouvons d montrer gt gt gt non non P ou non Q lt gt P et Q Th or me pour toutes propositions Q P non non P ou non Q lt gt P et Q 226 D monstration de propositions Cette propri t permet de r duire plus rapidement l alternative ci dessus En remar quant que x lt 1 est quivalent not x gt 1 et que x gt 2 est quivalent not x lt 2 on crit la condition not x lt 1 x gt 2 sous la forme not not x gt 1 not x lt 2 Il ne reste qu utiliser le th or me pr c dent avec P x gt 1 et Q x lt 2 On obtient alors P et Q c est dire x gt 1 amp amp x lt 2 Si vous ne vous int ressez pas aux propri t s alg briques des connecteurs logiques ou si vous n tes pas curieux de voir notre programme d montrer des propri t s abstraites vous pouvez passer la section suivante Propri t s alg briques des connecteurs propositionnels On tablit en math matiques que le et et le ou sont des op rations associatives et commutatives Ces propri t s sont communes aux connecteurs propositionnels et aux op rations arithm tiques et x Par exemple pour l addition la commutativit signifie qu on peut additionner les nombres dans n importe
115. appel s polyn mes creux Par opposition nous avions appel polyn mes pleins les polyn mes de la section 3 3 repr sent s par le tableau des coefficients de leurs mon mes Une repr sentation plus compacte des polyn mes creux utilise tout naturellement la liste ordonn e des coefficients non nuls avec leurs degr s respectifs Il s agit donc de listes de paires d entiers Dans cette repr sentation le polyn me 1 2X serait let p 1 0 2 3 p int int list 1 0 2 3 Nous allons red finir les op rations sur les polyn mes en travaillant sur des polyn mes creux Impression des polyn mes creux L impression est tr s simple nous utilisons exactement la m me fonction d impression des mon mes que dans le cas des polyn mes pleins mais nous l it rons sur la liste des coefficients l aide de la fonctionnelle do_list let imprime_polyn me_creux p do_list function a degr gt imprime_mon me a degr p imprime_polyn me_creux int int list gt unit lt fun gt imprime_polyn me_creux p 1 2x 78 unit Les amateurs de casse t te compareront la fonction imprime_polyn me_creux avec la fonction do_list uncurry imprime_mon me ou m me compose do_list uncurry imprime_mon me L addition est un peu plus compliqu e En effet elle op re un filtrage en parall le sur les deux polyn mes arguments Ce filtrage est complexe et utilise des traits nouveaux
116. argument n est pas vide et qu on appelle sa t te t et son reste r t r alors retourner t La clause _ gt signifie comme d habitude dans tous les autres cas La fonction failwith est une fonction pr d finie qui signale une erreur en anglais failwith signifie chouer avec Vous devinez donc que failwith t te signale une erreur dans la fonction t te t te l Exception non rattrap e Failure t te Le syst me nous signale ainsi une exception non rattrap e Uncaught exception c est dire un chec avec pour message la cha ne t te Failure t te Nous re viendrons sur ce m canisme d chec et sur la notion d exception au chapitre 7 Comme d habitude il n est pas obligatoire de nommer une partie de la valeur argu ment qu on n utilise pas Par exemple il n est pas n cessaire de nommer la t te d une liste pour retourner son reste on dit aussi la queue de la liste let reste function li ire r _ gt failwith reste reste a list gt a list lt fun gt reste 1 2 3 4 int list 2 3 4 5 2 Programmation assist e par filtrage Il est facile de d finir une fonction qui additionne tous les l ments d une liste d entiers si la liste est vide alors le r sultat est 0 sinon on ajoute le premier l ment de la liste la somme des l ments du reste de la liste let rec somme function D gt 0 x 1 gt
117. au contenu du programme On se convainc facilement de la validit de la r gle pr c dente en remarquant que les deux fonctions retournent toujours le m me r sultat quel que soit leur argument En effet function x gt f x y s value comme f y en rempla ant z par y dans Effets et valuation 53 f x On peut galement consid rer que cette r gle est la simple traduction de la d finition math matique des fonctions la fonction f est celle qui tout l ment x de son ensemble de d part fait correspondre son image par f c est dire f x La fonction f est donc la correspondance x f x c est exactement ce que traduit la r gle f function x gt f x Cette r gle est appel e r gle d extensionnalit ou encore r gle 7 la lettre grecque 7 se prononce ta Quand on remplace f par l expression plus complexe function x gt f x on dit qu on fait une 7 expansion Inversement quand on sim plifie function x gt f x en f on fait une 7 contraction La plupart du temps nous emploierons la r gle 7 dans le sens de la simplification 7 contraction Les conventions syntaxiques de d finition et d application des fonctions se combinent avec la r gle 7 pour tablir que letgzx fx est quivalent let g ff En effet la convention syntaxique des d finitions de fonctions nous permet d crire let g function x gt fx au lieu de letgx fx Puis en appliquant la r gle 7 on simpli
118. but et de fin sont les m mes et que la sous cha ne qu ils d limitent est un palindrome D finitions par cas le filtrage 27 Fonction r cursive plusieurs arguments Pour plus d efficacit nous r crivons la fonction palindrome en comparant di rectement les caract res de la cha ne argument deux deux sans cr er de sous cha nes On prend donc deux indices dans la cha ne argument s L indice i d marre au premier caract re l indice j d marre au dernier caract re au d part de la boucle on a donc n cessairement lt j sauf si la cha ne est vide chaque tape on compare les car act res d indice et j S ils sont gaux on continue sinon la cha ne n est videmment pas un palindrome La r cursion s arr te quand l indice atteint ou d passe j Dans le cas j on est sur le caract re central de la cha ne et il n y a rien faire il ne reste qu un caract re examiner forc ment gal lui m me s est un palindrome Dans le cas i gt j il n y a rien faire non plus on a d pass le milieu de la cha ne en ayant compar deux deux tous les caract res donc s est un palindrome Cet exemple nous fournit notre premi re fonction r cursive plusieurs arguments let rec palin s i j G gt j II s i s j amp amp palin s i 1 j 1 palin string gt int gt int gt bool lt fun gt let palindrome s palin s 0 string_length s 1 pa
119. c est vraiment facile vous Caml c est un langage de la sixi me Peut on aimer vraiment g n ration non Aimer ne pas aimer est ce vraiment la C est vrai que si Caml n existait pas il question faudrait l inventer d urgence C aime Je suis cat gorique Caml est un langage l Beaucoup tr s simple Sans aucune retenue En Caml c est trop simple les programmes Pourquoi cette attirance marchent toujours Comment expliquer ce sentiment Un tel langage quelle aubaine pour les Peut on aimer vraiment humains Aimer ne pas aimer est ce vraiment la Caml a c est du langage question 1 sexe Personnellement je ne suis pas concern e sm1 a para t int ressant l Pas de provocation s il vous pla t On m a dit que le sexe est important pour Ne me parlez pas des mammouths les humains SML dites vous Le sexe d accord mais l amour Jamais entendu parler de SML c est Avez vous entendu parler du Sida uoi cauchemar cauchemars reve reves k 2 3 140 Le docteur l J ai du mal comprendre je ne r ve Est ce une femme ordinaire jamais mal difficile Vos activit s nocturnes m int ressent l Je vous plains beaucoup Continuez tes vous certain d tre objectif a me para t bizarre Je peux tenter de vous aider Les cauchemars v
120. cas o condition est vraie dans le cas contraire le filtrage continue normalement en s quence l aide d une garde on crit facilement une version correcte de la fonction est_un let est_un function x when x un gt true _ gt false est_un int gt bool lt fun gt est_un 2 bool false On crit aussi la fonction valeur_d une_carte encore plus l gamment let valeur_d une_carte couleur _d atout function As _ gt 11 Roi _ gt 4 Dame _ gt 3 Valet __ gt 2 Petite_carte 9 c when c couleur _d atout gt 14 Petite_carte 10 _ gt 10 _ gt 0 valeur_d une_carte couleur gt carte gt int lt fun gt Valet c when c couleur_d atout gt 20 Filtrage exhaustif filtrage partiel Enfin il faut se m fier des filtrages non exhaustifs c est dire des filtrages qui oublient des cas C est une des forces du filtrage de servir de guide pour facilement envisager tous les cas concernant une structure de donn es il faut donc en profiter pleinement Si vous oubliez d envisager certains cas le compilateur met un message d avertissement et il faut en tenir compte Voici un exemple caricatural de filtrage non exhaustif let vide function gt true Entr e interactive gt let vide function gt true S Mie ne He NARSA AARNA SAS Attention ce filtrage n est pas exhaustif vide a list gt bool
121. cha ne de caract res La traduction na ve de la d finition des cha nes reconnues par une expression rationnelle m ne un algorithme par essais et erreurs qui est tr s inefficace dans les cas d favorables Intuitivement pour reconna tre 310 Recherche de motifs dans un texte une expression de la forme e il faut essayer de reconna tre e toutes les positions possibles dans la cha ne Si plusieurs expressions de ce type se suivent comme dans e1 e2 en le nombre de combinaisons essayer devient tr s grand La mani re efficace de d terminer si une expression rationnelle reconna t une cha ne de caract res est de transformer d abord l expression rationnelle en un automate qui reconna t les m mes mots puis d ex cuter l automate sur ladite cha ne de caract res Intuitivement un automate est une machine tr s simplifi e sp cialis e dans la recon naissance des mots Elle se compose d un certain nombre d tats repr sent s par des cercles reli s entre eux par des transitions repr sent es par des fl ches Les transitions sont tiquet es ou bien par une lettre ou bien par le mot vide CCC La r gle du jeu est la suivante partir d un tat on a le droit de passer dans un autre tat soit parce qu il existe une transition marqu e de l tat de d part vers l tat d arriv e soit parce qu il existe une transition marqu e x o x est le prochain caract re de la cha ne
122. chouer au pr texte qu on ne peut pas r p ter un nombre flottant de fois une liste d ordres r p ter 3 1 fois n a pas de sens C est cette derni re solution que nous adoptons Nous d finissons donc une fonction de conversion d un nombre en une valeur enti re qui choue si son argument est flottant let valeur _enti re function Entier i gt i Flottant f gt failwith entier attendu valeur_enti re nombre gt int lt fun gt Voyons maintenant le code de la fonction qui ex cute les ordres Nous d taillerons ensuite le code qui correspond aux ordres nouveaux exception Fin_de_proc dure L exception Fin_de_proc dure est d finie let rec ex cute_ordre env function Av e gt avance flottant valeur_expr env e Re e gt avance flottant valeur_expr env e Tg a gt tourne flottant valeur_expr env a 172 Syntaxe abstraite syntaxe concr te Td a gt tourne flottant valeur_expr env a Lc gt fixe_crayon true Bc gt fixe_crayon false Ve gt vide_ cran Rep n 1 gt for i 1 to valeur _enti re valeur_expr env n do do_list ex cute_ordre env 1 done Si ei e2 alors sinon gt if compare _ nombres valeur_expr env ei valeur_expr env e2 then do_list ex cute_ordre env alors else do_list ex cute_ordre env sinon Stop gt raise Fin_de_proc dure Ex cute nom_de_proc dure args gt let d finition d finition _de nom_de
123. composantes les Repr sentation et v rification des propositions 213 et ou non qui interviennent ensuite pour produire l ensemble des lignes de la table nous crirons une autre fonction qui envisagera l ensemble des valeurs possibles des propositions l mentaires Pour simplifier l utilisation du d monstrateur nous ferons finalement un analyseur syntaxique qui nous permettra d entrer facilement les propositions Cela devient presque de la routine maintenant nous d finirons le type des propositions et l analyseur syntaxique analysera une cha ne de caract res qu il transformera en une valeur du type des propositions 12 4 Repr sentation et v rification des propositions Nous commen ons par le module prop qui d finit le type des propositions et impl mente les fonctions d valuation d une proposition et de g n ration de la com binatoire des possibilit s d crites ci dessus Le type des propositions Le type des propositions comporte des constructeurs pour les connecteurs de base Non Et Ou et des constructeurs pour les connecteurs d finis partir des connecteurs de base Implique et quivalent Pour repr senter les propositions l mentaires comme P ou Q qu on appelle aussi variables propositionnelles on fournit le constructeur Variable qui prend en argument une cha ne de caract res le nom de la proposition Ces variables repr sentent les propositions dont on ne conna t pas la
124. crit n est pas compl tement r aliste pour simplifier nous n avons pas rendu compte d un certain nombre de traits des vrais processeurs traits qui sont des cons quences directes de l architecture interne de ces processeurs Par exemple dans le processeur MIPS R3000 dont nous nous sommes inspir s certaines instructions prennent effet retardement un branchement par exemple n est pas ex cut imm diatement le processeur ex cute syst matiquement l instruction qui suit le branchement avant de se d router effectivement l endroit in diqu Le pico processeur ne simule pas ce fait De m me nous n avons pas essay de simuler fid lement le temps d ex cution des programmes m me si sur un processeur RISC la plupart des instructions s ex cutent en un cycle d horloge certaines instruc tions arithm tiques multiplication et division prennent g n ralement plus de temps pis les acc s la m moire prennent des temps tr s variables suivant qu on tombe dans la m moire cache de niveau 1 2 3 cycles typiquement celle de niveau 2 10 30 cycles dans la m moire principale 40 100 cycles ou dans la m moire virtuelle des millions de cycles Par cons quent le programme d crit dans ce chapitre est davantage un interpr teur d un langage d assemblage raisonnablement r aliste qu un simulateur 276 Simulation d un processeur fid le d un processeur r el Simuler fid lement un
125. d finissant toutes les caract ristiques du crayon c est donc un type et un type enregistrement Les coordonn es du crayon et son angle de vis e sont des nombres flottants et le statut lev ou non du crayon est videmment un bool en Cela nous conduirait donc d finir le type tat comme type tat x float y float vis e float lev bool et l tat courant du crayon comme let crayon x 0 0 y 0 0 vis e 0 0 lev false Cependant ce type ne nous permet pas de faire voluer le crayon Or nous n avons qu un seul crayon dont nous voulons faire varier dynamiquement les caract ristiques Pour cela il faut explicitement d clarer au syst me Caml que nous d sirons modifier physiquement les champs de l enregistrement qui mod lise le crayon Comme expliqu la section 6 6 il suffit d indiquer que les champs du type tat sont modifiables en faisant pr c der les tiquettes correspondantes du mot cl mutable lors de la d finition du type type tat mutable x float mutable y float mutable vis e float mutable lev bool Le type tat est d fini Le contr leur de type nous autorisera maintenant changer les valeurs des car act ristiques d un objet du type tat La construction d une valeur d un enregistrement champs mutables ne diff re pas du cas habituel Nous d finissons donc le crayon comme une donn e du type tat par false
126. d ex cution de la commande grep impl ment e dans ce chapitre pourrait tre fortement am lior e Il y a deux sources importantes d inefficacit la d terminisation de l automate d une part et d autre part l ex cution de l automate sur les lignes des fichiers La d terminisation est un processus essentiellement co teux dans le pire des cas la taille de l automate produit est exponentielle en la taille de l expression rationnelle Dans les cas courants on l acc l re consid rablement en groupant les transitions sortant d un tat et aboutissant sur le m me tat Par exemple les transitions que nous avons tiquet es tout sauf t tout sauf e dans les exemples repr sentent en fait 255 transitions du m me tat vers le m me tat La fonction de d terminisation pr sent e 322 Recherche de motifs dans un texte ci dessus ne tient pas compte de ce genre de partage et donc a tendance refaire 255 fois les m mes calculs dans des situations de ce type L introduction dans les automates non d terministes de transitions de la forme tout sauf permet d viter cette source d inefficacit au prix de nombreuses complications dans le programme Pour ce qui est de l ex cution de l automate d terministe le probl me n est pas d ordre algorithmique mais provient du syst me Caml Light lui m me il faut ex cuter quelque chose de tr s simple une boucle essentiellement sur un grand volum
127. dans les registres et non pas dans la pile D tecter les variables locales qui se pr tent ce traitement et leur attribuer des registres de mani re coh rente est un probl me difficile Une troisi me direction est d am liorer la structure interne du compilateur Nous avons vu que pour afficher correctement les erreurs de typage il faudrait annoter les n uds de l arbre de syntaxe abstraite par des num ros de ligne et des positions dans le code source D autres informations devraient elles aussi figurer en annotations sur l arbre de syntaxe abstraite comme le type attribu chaque n ud par la phase de typage ainsi que les besoins en registres de chaque expression Cela viterait de recalculer de nombreuses fois ces informations lors de la compilation Bibliographie Parmi les nombreux ouvrages publi s sur les compilateurs nous recommandons Compilateurs principes techniques et outils de Aho Sethi et Ullman Inter ditions et Modern compiler implementation in ML d Appel Cambridge University Press 16 Recherche de motifs dans un texte Un programme pour les toiles ECHERCHER LES OCCURRENCES d un motif dans un texte est une op ration cruciale dans de nombreux outils informatiques traitement de texte diteurs navigateurs Web etc Nous impl mentons ici un outil qui affiche toutes les lignes d un fichier contenant un motif donn dans le style de la commande grep d Unix Pour ce faire nous introd
128. de disques d une tige l autre Voyons tout d abord la fonction qui ajoute un disque au sommet d une tige Par exemple dans un jeu quatre disques ajouter le troisi me disque une tige qui ne comprend que le disque num ro 4 correspond l valuation de ajoute_disque 3 2 4 qui retourne 1 3 41 let ajoute_disque disque d calage disques as tige d calage 1 disque disques ajoute_disque a gt int a list gt int a list lt fun gt On d finit la fonction sommet pour consulter le disque qui se trouve au sommet d une tige et la fonction enl ve_sommet pour ter le sommet d une tige plus exactement pour renvoyer la tige priv e de son sommet 90 Listes let sommet function d calage sommet reste gt sommet d calage gt failwith sommet tige vide sommet a b list gt b lt fun gt let enl ve_sommet function d calage sommet reste gt d calage 1 reste d calage gt failwith enl ve sommet tige vide enl ve_sommet int a list gt int a list lt fun gt Nous pouvons maintenant simuler un mouvement en d pla ant un disque d une tige l autre La proc dure prend en argument des r f rences sur les tiges concern es et les modifie physiquement au passage let d place nom_ d part tige_d part nom_arriv e tige_arriv e imprime Je d place un disque de nom_d
129. de f temporaires de f pointeur de pile L entier argument des constructeurs Local_indirect et Local_direct repr sente la position relative de la variable locale dans le bloc d activation Le point de rep re est l adresse du mot contenant le premier param tre Les positions positives correspondent aux variables locales les positions n gatives aux param tres Comme pour les valeurs globales Local_indirect signifie qu il faut faire une indirection cette adresse pour obtenir la valeur de la variable alors que Local_direct signifie que cette adresse est la valeur de la variable adresse de retour position relative de x a lprofondeur_pile param tres pass s f par g variable x pointeur de pile L acc s aux variables locales se fait par adressage relatif au pointeur de pile le registre num ro 30 aussi appel sp Le compilateur garde trace du d calage entre le pointeur de pile et le mot contenant l adresse de retour dans le bloc d activation courant dans la variable profondeur_pile Cette variable augmente lorsqu on alloue de nouveaux temporaires et diminue quand on les lib re Fichier compil ml let profondeur _pile ref O Compilation 293 let r serve_pile n printf sub sp d sp n n taille_du_mot profondeur_pile lprofondeur_pile n taille_du_mot and lib re_pile n printf add sp d sp n n taille_du_mot profondeur_pile lprofondeur_pile n tai
130. de la d claration la plus r cente de chaque variable Il associe galement aux noms de proc dures et de fonctions leurs d clarations noms des param tres corps de la proc dure etc Le module envir fournit le type abstrait env des environnements et les op rations de base sur ce type Pour pouvoir r utiliser le module envir nous allons param trer le type env par le type des informations associ es aux variables Le type fourni par le module envir est donc a env o a est le type des informations associ es aux variables Dans le v rificateur nous associons des expressions de types aux variables et utilisons donc des environnements de type expr_type env Dans le compilateur section 15 3 ce sont des informations de compilation que nous associerons aux variables Fichier envir mli open syntaxe type a env value environnement_initial string d cl_proc list gt string d cl_fonc list gt a env and ajoute_variable string gt a gt a env gt a env and cherche_variable string gt a env gt a and cherche_fonction string gt a env gt d cl_fonc and cherche_proc dure string gt a env gt d cl_proc exception Pas_trouv of string En voici une impl mentation simple base de listes d associations Typage 285 Fichier envir ml open syntaxe open interp type a env vars string a list procs string d
131. des quantit s formelles Par exemple en math matiques si x est un entier alors x x est gal 0 Il n est pas n cessaire de conna tre la valeur de x pour obtenir le r sultat du calcul on parle d ailleurs plut t de simplification que de calcul Au contraire en Caml on ne peut parler d un nom s il n a pas t pr c demment d fini On ne peut donc pas calculer x x si x n est pas li une valeur pr cise car il est alors impossible de faire effectivement la soustraction x X Entr e interactive gt X X gt L identificateur x n est pas d fini Le langage indique ici que notre phrase est erron e puisque le nom x n a jamais t d fini on dit encore que x n est pas li Mais le r sultat est videmment le bon d s que l identificateur est d fini nous pouvons par exemple faire le calcul avec s s S int 0 Une autre diff rence essentielle entre un programme et une d finition math matique r side dans la notion d efficacit un langage de programmation calcule des valeurs de 8 Premiers pas mani re effective ce qui demande un certain temps Si ce temps devient prohibitif on peut consid rer que le programme est incorrect m me si l on peut prouver qu il donnerait un jour le bon r sultat En math matiques cette notion de temps de calcul est sans importance Un autre cueil majeur de l informatique est qu elle ne conna t pas l infini P
132. donn s trois arguments f b et l la fonctionnelle list_it effectue de multiples compositions de la fonction deux arguments f en utilisant les l ments de la liste l comme premiers arguments de f l l ment de base b est utilis pour le second argument du premier appel f puis le r sultat de chaque appel f est pass en second argument de l appel suivant list_it est caract ris e par list_it f e1 e2 en b f e1 f e2 f enb En termes encore plus savants et en utilisant l op rateur math matique de composition des fonctions o on crirait list_it f e1 e2 en b f e1 o f e2 o o f en b let rec list_it f 1 b match 1 with O gt b x reste gt f x list_it f reste b list_it a gt b gt b gt a list gt b gt b lt fun gt Intuitivement list_it fait aussi de la r criture de liste elle remplace toutes les occurrences de par f et le final par la valeur initiale b list_it l 2 list _it f lb AN AN e1 ee e1 f JON JUN 2 UE 2 S X ZN JUN En En b Par exemple la fonction qui copie une liste est facile d finir elle doit remplacer tous les de la liste par d autres et le final par La fonction f qui fait ce travail de ne rien modifier et donc de remplacer par est simplement la fonction function x gt function 1 gt x 1 Nous l appelons cons et la d fini
133. e message raise Erreur Plan du programme 239 La fonction commence par ouvrir un canal d entr e et un canal de sortie sur les fichiers indiqu s au moyen des fonctions open_in_bin et open_out_bin Les fonctions de biblioth que open_in_bin et open_out_bin ouvrent les canaux en mode binaire garantissant que les caract res lus ou crits sur le canal sont exactement ceux que contiennent le fichier Au contraire les fonctions open_in et open_out ouvrent les canaux en mode texte sur certaines impl mentations de Caml Light il se produit alors des traductions en particulier sur les caract res de fin de lignes au moment de la lecture et de l criture Les fichiers compresser ne contiennent pas forc ment du texte il est donc n cessaire d op rer en mode binaire pour tre certain de retrouver les fichiers l identique apr s une compression suivie d une d compression La par tie difficile du travail c est dire la compression proprement dite est assur e par la fonction traitement pass e en argument traite_fichier Cette fonction re oit un canal ouvert sur l entr e et un canal ouvert sur la sortie Elle est cens e compresser ou d compresser son entr e sur sa sortie Lorsque la compression s ach ve sans erreur on ferme les canaux d entr e et de sortie fonctions close_in et close_out et on efface le fichier d entr e fonction remove du module sys Aux yeux de l utilisateur
134. e ci dessus La seule diff rence est que pour des raisons d efficacit le constructeur Caract res prend en argument non pas un seul caract re mais une liste de caract res L expression Caract res c1 c repr sente l alternative c Cn La syntaxe concr te des expressions rationnelles ressemble celle employ e par grep Elle introduit un certain nombre de constructions syntaxiques d riv es des con structions de base alternative s quence r p tition e Le point repr sente n importe quel caract re c est dire l alternative entre tous les caract res Syntaxe abstraite et syntaxe concr te des motifs 307 e Un caract re non sp cial repr sente l expression mono caract re correspondante La barre oblique invers e backslash sert d chappement pour les caract res sp ciaux suivi de n importe quel autre caract re repr sente ce caract re En particulier est le caract re e Les crochets repr sentent des ensembles de caract res Par exemple aeiou repr sente alelilo u Le tiret d note des intervalles 0 9 repr sente tous les chiffres A Za z toutes les lettres On prend le compl mentaire d un ensemble en mettant un chapeau juste apr s le crochet 0 9 repr sente tout caract re qui n est pas un chiffre e Les combinaisons d expressions rationnelles sont not es comme suit Combinaison Notation Exemple Signification Alternative infixe lellalles
135. effet le corps de la fonction l expression e1 par exemple peut faire r f rence f lors d un appel r cursif L environnement de la fermeture doit donc contenir une liaison de f la valeur de f c est dire la fermeture que nous sommes en train de construire Si nous notons F la fermeture de f alors l environnement de cette fermeture doit tre f F env_courant Il est clair que la fermeture F et l environnement tendu qu elle comporte sont des objets circulaires Pour r sumer graphiquement ces contraintes La boucle d interaction 331 Fermeture d finition environnement l Lp env_courant Pour construire la fermeture F l astuce est de commencer par construire une ferme ture dont le champ environnement est initialis une valeur quelconque par exemple l environnement vide On construit ensuite l environnement tendu avec cette valeur provisoire Il suffit alors de modifier physiquement le champ environnement de F pour y stocker lenvironnement tendu La modification physique construit le cycle d sir Impression des valeurs Nous terminons le module eval par une fonction d impression des valeurs qui ne pr sente aucune difficult Fichier eval ml let rec imprime_valeur function Val_ nombre n gt print_int n Val_bool enne false gt print_string false Val_bool enne true gt print_string true Val_paire vi v2 gt print_string
136. es aux arbres de syntaxe abstraite Mais ce calcul s effectue soit directement et il s agit alors d interpr tation valuateur des tautologies du langage graphique de mini Caml soit en deux tapes corr l es en produisant d abord une nouvelle donn e partir de l arbre de syntaxe abstraite puis en valuant cette nouvelle donn e et il s agit maintenant de compilation compilation d un automate partir d une expres sion rationnelle ou production de code pour la pico machine partir d un programme Pascal G n ralement les s mantiques compilateur sont plus efficaces que celles in terpr teur car la phase de compilation permet d une part d anticiper et de pr parer la phase d valuation et d autre part de mettre en facteur certaines parties r p titives de l valuation Dans le cas d un langage de programmation cet avantage de la com pilation est particuli rement clair lorsque l interpr teur doit valuer un programme il lui faut constamment analyser l arbre de syntaxe abstraite alors qu un code compil n a plus de questions se poser le compilateur a fait une fois pour toute l analyse L exemple des boucles est frappant cet gard l interpr te r analyse le corps de la boucle chaque tour de boucle alors que le code compil ex cute directement ce corps Compilation et interactivit Int ressons nous plus particuli rement la derni re partie de ce livre celle
137. et le pas est donc pas 7 180 x R let cercle r let pas r pi_sur_180 in for i 0 to 360 do avance pas tourne 1 0 done cercle float gt unit lt fun gt let arc_gauche r angle let pas r pi_sur_180 in for i 0 to angle do avance pas tourne 1 0 done arc_gauche float gt int gt unit lt fun gt let arc_droit r angle let pas r pi_sur_180 in for i 0 to angle do avance pas tourne 1 0 done arc_droit float gt int gt unit lt fun gt vide_ cran cercle 50 0 arc_gauche 25 0 180 arc_droi it 25 0 180 fixe_crayon true tourne 90 0 avance 25 0 fixe_crayon false cercle 2 0 fixe_crayon true avance 50 0 fixe_crayon false cercle 2 0 unit 154 Graphisme 8 6 Le flocon de von Koch Pour le flocon de von Koch il faut d finir le motif de base dont la taille d pend du param tre c et de la g n ration n Appelons motif cette proc dure la g n ration 0 on avance simplement de la longueur du c t c Sinon il faut tracer les quatre morceaux du motif de base en tournant des bons angles Ces quatre morceaux sont eux m mes des motifs mais de la g n ration pr c dente Chaque morceau est donc obtenu par un appel r cursif motif de la forme motif n 1 d o d est la longueur d un morceau Il ne nous reste plus qu d terminer cette longueur Or il est facile de voir qu en parcourant quatre fois la distance d en suivant le
138. exemple voici ce qu on obtient pour la tige 1 2 3 51 c est dire une case libre puis trois disques de largeur 2 3 et 5 let imprime ligne print_string ligne print_newline imprime string gt unit lt fun gt do_list imprime tige 5 1 2 3 51 lt lt gt gt lt lt lt gt gt gt lt lt lt lt lt gt gt gt gt gt unit Par la suite nous allons avoir besoin d afficher non pas une tige mais trois tiges c te c te La fonction recolle cr e la liste des lignes afficher partir des trois listes de lignes correspondant aux trois tiges let rec recolle 11 12 13 match 11 12 13 with J 0 0O gt 0 t1 ri t2 r2 t3 r3 gt t1 t2 t3 recolle r1 r2 r3 _ gt failwith recolle recolle string list gt string list gt string list gt string list lt fun gt L affichage d une configuration consiste simplement imprimer les lignes qui repr sentent les disques puis imprimer les trois bases des tiges let imprime_jeu nombre_de_disques d part milieu arriv e let dessin recolle tige nombre_de_disques d part tige nombre_de_disques milieu tige nombre_de_disques arriv e in do_list imprime dessin let b base_de_tige nombre_de_disques in imprime b b b imprime_jeu int gt int int list gt int int list gt int int list gt unit lt fun gt Nous impl mentons maintenant les d placements
139. exemple pour crire directement l adresse de L assembleur 271 retour d une fonction sur la pile Fichier stockage ml let r soudre tiquette adresse nom_ tiq let valeur try hashtbl__find asm table_ tiq nom_ tiq with Not_found gt raise Erreur tiquette nom_ tiq let nouvelle_instruction match asm code d code_adresse adresse with Op op ration regi _ reg2 gt Op op ration regi Imm valeur reg2 Jmp _ reg gt Jmp Imm valeur reg Braz reg _ gt Braz reg valeur Branz reg _ gt Branz reg valeur _ gt raise Erreur r soudre_ tiquette in asm code d code_adresse adresse lt nouvelle_instruction ind finie in let extraire_code do_list r soudre_ tiquette asm _r soudre sub_vect asm code 0 d code_adresse asm pc Finalement la fonction extraire_code appelle r soudre_ tiquette sur la liste des tiquettes non r solues puis renvoie le tableau des instructions assembl es La fonction sub_vect est l analogue pour les tableaux de la fonction sub_string des cha nes de caract res elle extrait un sous tableau d une certaine longueur partir d un certain indice La lecture et l assemblage des programmes Le module lecture fournit l unique fonction programme qui lit un programme de la pico machine depuis un flux de caract res l assemble puis fait r soudre les tiquettes par la fonction extraire_code qui renv
140. fini Le mot cl type introduit la d finition du nouveau type polyn me Apr s le signe on crit la liste des possibilit s du type en cours de d finition Les noms Plein et Creux sont appel s les constructeurs de valeurs du type s il ny a pas d ambigu t on dit simplement constructeurs Comme d habitude la barre verticale indique l alternative et se lit ou Le mot cl of indique le type de l argument du constructeur Le type polyn me comprenant les valeurs d un type plus les valeurs d un autre type on dit que c est un type somme On peut maintenant cr er des valeurs de type polyn me en appliquant l un des deux constructeurs du type polyn me une valeur du type correspondant Par exemple let p1 Plein l1 2 31 pi polyn me Plein l1 2 31 let p2 Creux 1 0 1 100 p2 polyn me Creux 1 0O 1 100 Maintenant p1 et p2 sont du m me type et pourront tre arguments d une m me fonction Polyn mes pleins et polyn mes creux 111 Le filtrage est tendu tous les types somme et permet tant donn e une valeur du type somme de d terminer dans quel cas se trouve cette valeur Pour le type polyn me le filtrage va donc nous permettre d impl menter la fonction est un polyn me plein let est_un_polyn me_ plein function Plein _ gt true Creux _ gt false est_un_polyn me_plein polyn me gt bool lt fun gt Une fonction travai
141. function on n value donc rien lors de leur d finition 364 Un synth tiseur de types L inconv nient de cette m thode est qu elle modifie l algorithme de base en par ticulier elle refuse de g n raliser les applications quelles qu elles soient Cela inter dit de d finir une fonction polymorphe par application partielle let map_id map identit est alors typ de fa on monomorphe En pratique ce n est pas si grave car il suffit de faire une 7 expansion en ajoutant un param tre suppl mentaire On crirait let map_id 1 map identit l Cette derni re phrase n est pas vraiment plus complexe que l application partielle on peut m me la juger plus claire L avantage fondamental de cette m thode est sa grande simplicit on conserve les m mes types qu avant l introduction des valeurs mutables et les fonctions manipulant les valeurs mutables sont sans danger compl tement polymorphes C est d ailleurs la m thode adopt e actuellement dans les compilateurs Caml let identit x x identit a gt a lt fun gt let map_id_poly 1 map identit 1l map_id_poly a list gt a list lt fun gt let map_id map identit map_id _a list gt _a list lt fun gt La variable de type not e _a par le syst me Caml correspond exactement aux variables de type inconnues de notre contr leur de type et comme elles la variable _a est susceptible de recevoir un t
142. gitimement ce genre de phrases d tre d nu es de sens et que c est souvent le cas Pourtant les d finitions r cursives sont tr s employ es en math matiques et en informatique domaines o l on se m fie beaucoup des phrases d nu es de sens Il existe donc forc ment des phrases qui se mordent la queue et pourtant poss dent une signification pr cise utilisable en math matiques ou informatique Toute la difficult des d finitions r cursives provient de la d tection des cas o la r cursivit entra ne le non sens Une d finition r cursive sens e est qualifi e de bien fond e Nous verrons par l exemple ce que cela veut dire 20 R cursivit L intuition la plus simple qu on puisse donner de la r cursivit est l id e de recommencer la m me chose La r cursivit est pr sente aussi dans le domaine graphique un exemple nous est donn par le c l bre dessin qui orne les couvercles de Vache qui rit figurant une vache qui porte en boucles d oreilles des bo tes de Vache qui rit dont les couvercles comportent donc le dessin lui m me Dans le domaine physique l infinit d images qui appara t dans deux miroirs quasi parall les est aussi une bonne analogie exp rience habituelle chez le coiffeur Prenons un exemple plus informatique la tr s c l bre fonction factorielle qui retourne le produit des nombres entiers inf rieurs ou gaux son argument En math matiques el
143. gt a list gt a list lt fun gt concat ne 1 2 3 4 5 6 l int list 1 2 3 4 5 6 Filtrage simultan de deux valeurs Pour envisager tous les cas concernant la forme de deux listes il suffit de filtrer explicitement la paire des deux listes Ainsi la fonction suivante d termine si deux listes ont m me longueur let rec m me_longueur 11 12 match 11 12 with CE gt true _ restel _ reste2 gt m me_longueur restel reste2 _ _ gt false m me_longueur a list gt b list gt bool lt fun gt m me _ longueur 1 2 l m me_longueur 1 1 2 bool true bool false Op rations sur les polyn mes creux 85 Le filtre _ restel _ reste2 signifie si la premi re liste 11 n est pas vide et donc de la forme _ reste1 et si simultan ment la seconde liste 12 est non vide et de la forme _ reste2 alors En particulier les soulign s _ mettent bien en vidence qu on ne s int resse pas la t te des listes mais qu on a nomm leurs restes respectifs restei et reste2 Remarquez que le dernier cas du filtrage correspond des listes d in gales longueurs l une est puis e mais l autre ne l est pas En effet si les deux taient puis es le premier cas s appliquerait tandis que si aucune n tait puis e c est le second qui s appliquerait Autrement dit le cas _ _ regroupe en une
144. gt gt begin match flux with lt 0 9 as c gt gt Entier lire_entier int_of_char c 48 flux pise gt tampon 0 lt mc_ou_ident table lire_symbole 1 flux end lt c gt gt mc_ou_erreur table c G n ration de l analyseur Comme pour le mini Logo on construit le flux des lex mes par appels r p t s lire_lex me Fichier lexuniv ml let rec analyseur table flux stream_from function gt match flux with lt lire_lex me table lex me gt gt lex me lt gt gt raise Parse_failure 232 D monstration de propositions Finalement la g n ration d un analyseur lexical consiste simplement construire sa table des mots cl s puis appliquer partiellement l analyseur g n rique cette table Le r sultat de l application partielle est la fonction des flux de caract res vers les flux de lex mes d sir e Fichier lexuniv ml let construire_analyseur mots_cl s let table_des_mots_cl s hashtbl__new 17 in do_list function mot gt hashtbl__add table_des_ mots_cl s mot MC mot mots_cl s analyseur table_des_mots_cl s 12 9 Pour aller encore plus loin le hachage L id e du hachage vient de la constatation que la recherche d un objet dans une liste d association se r v le co teuse si l on doit faire beaucoup de recherches en particulier si ces recherches sont la plupart du temps
145. gt gt Tg n lt Mot tg nombre n gt gt Tg n lt Mot r p te Constante_ enti re n liste_d ordres 1 gt gt Rep n 1 lt Mot rep Constante_ enti re n liste_d ordres 1 gt gt Rep n 1 and liste_d ordres function lt Symbole suite_d ordres l Symbole gt gt 1 and suite_d ordres function lt ordre ord suite_d ordres l_ord gt gt ord 1_ord lt gt gt ordre lex me stream gt ordre lt fun gt liste_d ordres lex me stream gt ordre list lt fun gt suite_d ordres lex me stream gt ordre list lt fun gt La fonction suite_d ordres est la plus complexe Elle comprend deux filtres 168 Syntaxe abstraite syntaxe concr te e lt ordre ord suite_d ordres l_ord gt on s attend trouver un ordre ord ventuellement suivi d autres ordres que la fonction suite_d ordres placerait dans une liste 1_ord e lt gt dans tous les autres cas il n y a plus d ordres lire et la fonction ren voie la liste vide C est videmment ce cas qui arr te la r cursion de la fonction Remarquez que cette syntaxe autorise la r p tition d une liste d ordres vide Finalement un programme est une suite d ordres termin e par un point let analyse_programme function lt suite_d ordres 1l Symbole gt gt l analyse_programme lex me stream gt ordre
146. imprime_valeur vi print _string imprime_valeur v2 print_string Val_nil gt print_string Val_cons vi v2 gt imprime_valeur vi print _string imprime_valeur v2 Val_fermeture _ Val_ primitive _ gt print _string lt fun gt mn mn 17 3 La boucle d interaction Nous allons maintenant mettre autour de l valuateur une boucle d interaction sur le mod le de la boucle d interaction de Caml Nous commen ons par construire un environnement initial d valuation comprenant un certain nombre de fonctions de base sur les entiers et les bool ens arithm tique comparaisons etc Pour ce faire il faut habiller les fonctions Caml correspondantes pour qu elles op rent non plus sur les types de donn es Caml mais sur leurs repr sentations dans le type valeur Fichier interprete ml open syntaxe open eval let code_nombre n Val_nombre n 332 Ex cution d un langage fonctionnel and d code_nombre function Val_nombre n gt n _ gt raise Erreur entier attendu and code_bool en b Val_bool enne b and d code_bool en function Val_bool enne b gt b _ gt raise Erreur bool en attendu x Pour transformer une fonction Caml en valeur fonctionnelle let primi codeur calcul d codeur Val_primitive function val gt codeur calcul d codeur val and prim2 codeur calcul d codeuri d codeur2 Val_primitive
147. insertion ins re correctement un l ment dans une liste Nous consid rons donc la propri t P l suivante sous l hypoth se que est une liste bien tri e ins re l ment l est une liste elle aussi bien tri e qui comprend l ment et tous les l ments de la liste l 1 P est vraie pour En effet ins re l ment vaut l ment qui est forc ment bien tri e comprend l ment et tous les l ments de la liste vide 2 Supposons P l vraie Alors P x l est vraie aussi En effet d apr s la d finition de la fonction ins re si l ment lt x alors ins re l ment x l vaut l ment x 1 qui contient l ment et tous les l ments de la liste argument x l et ce r sultat est bien tri puisque x est bien tri e par hypoth se et que l ment lt x Dans le cas o l ment gt x alors ins re l ment x l vaut x ins re l ment l Cette liste est bien tri e car d apr s l hypoth se de r currence P l est vraie donc ins re l ment l est bien tri e mais x est le plus petit l ment de x ins re l ment l puisque c tait d j le plus petit l ment de x l et qu il est plus petit que l ment De plus la liste x ins re l ment l contient l ment et tous les l ments de x 1 car elle contient videmment x et par hypoth se de r currence ins re l ment l contient tous les l ments de l et l l ment ins rer l ment En conc
148. l aide des op rateurs et et ou des bool ens Par d finition si P et Q sont des bool ens alors l expression P et Q est vraie quand P et Q sont vraies simultan ment Naturellement l expression P ou Q est vraie d s que P ou bien Q est vraie et a fortiori si P et Q sont vraies En Caml le ou se note et le et amp amp Les op rateurs et amp amp remplacent certaines formes d expressions conditionnelles En effet la construction if P then true else Q calcule la m me valeur bool enne que P Q et de m me if P then Q else false calcule la m me valeur que P amp amp Q Bien s r if P then true else false se simplifie en P On clarifie souvent les programmes en appliquant ces quivalences Voici donc une version plus simple de palindrome qui utilise les op rateurs bool ens let rec palindrome s let longueur string_length s in longueur lt 1 s 0 s longueur 1 amp amp palindrome sub_string s 1 longueur 2 palindrome string gt bool lt fun gt Les constructions et amp amp ont les m mes priorit s relatives que et c est dire le m me parenth sage implicite Ainsi de la m me fa on que a b c se lit en fait a b c l expression a b amp amp cest lue a b amp amp c par la machine On lit alors le code de palindrome tr s naturellement une cha ne est un palindrome si sa longueur est inf rieure 1 ou si ses caract res de d
149. la retourner en r sultat Les valeurs fonctionnelles sont cr es lors des d finitions de fonctions comme nous venons de le voir Cependant on peut aussi construire des valeurs fonctionnelles sans leur donner de nom en utilisant des fonctions anonymes Ces fonctions sont in troduites par le mot cl function suivi de la formule qui les d finit function x gt 2 x x 1 int gt int lt fun gt Encore une fois Caml nous indique par le symbole que nous avons fait un simple calcul dont le r sultat est de type int gt int et dont la valeur est une fonction lt fun gt On applique les fonctions anonymes comme toutes les autres fonctions en les faisant suivre de leur s argument s function x gt 2 x x 1 2 int 5 D finition de fonctions l aide de fonctions anonymes Il existe un autre style de d finitions math matiques de fonctions Soit successeur Z Z x gt x l Ce style insiste sur le fait que successeur est une fonction qui tout l ment x de l ensemble Z des entiers associe x 1 l aide des fonctions anonymes cette d finition se traduit tr s simplement en Caml let successeur function x gt x 1 successeur int gt int lt fun gt Contraintes de type Pour se rapprocher encore du style de la d finition math matique on peut m me ajouter une contrainte de type sur le nom de la fonction qui rend compte de l indication succe
150. la technologie actuelle il aurait fallu avec le programme de la premi re version de compte_hanoi Notions de complexit 35 let nombre_de_secondes_par_an 3600 0 24 0 x 365 25 nombre_de_secondes_par_an float 31557600 0 let nombre _ d additions_par_an nombre_de_secondes_par_an 1E9 nombre_d additions_par_an float 3 15576e 16 compte_hanoi_rapide 64 0 nombre_d additions_par_an float 584 542046091 c est dire plus de 584 ann es pour achever le calcul Nous sommes donc ici en pr sence d une fonction qui donne effectivement le bon r sultat au sens des math matiques mais qui le calcule tellement lentement qu elle devient inutilisable la diff rence des math matiques il ne suffit donc pas en informatique d crire des programmes corrects il faut encore que leur complexit ne soit pas trop lev e pour qu ils calculent le r sultat correct en un temps raisonnable La fonction compte_hanoi_na ve n cessite 2 1 additions pour l argument n Son temps de calcul est donc proportionnel une puissance 2 dont l exposant est son argument n l algorithme est exponentiel La seconde version utilisant la multiplication n cessite n multiplications l algorithme est donc lin aire Un algorithme lin aire de mande un temps de calcul qui augmente comme la valeur de son argument O n ce qui est raisonnable En effet cette version nous aurait permis d obtenir notre r
151. le ou la ou les S quence concat nation x 0 9 x puis un chiffre R p tition postfixe 0 9 x z ro un ou plusieurs chiffres R p tition stricte postfixe 0 9 un ou plusieurs chiffres Option postfixe un signe plus un signe moins ou rien L alternative a la priorit la plus faible puis la s quence puis les r p titions Pour passer outre ces priorit s on dispose des parenth ses e Un signe chapeau en d but d expression rationnelle signifie que le mot reconnu doit appara tre en d but de ligne Un signe dollar en fin d expression rationnelle signifie que le mot reconnu doit se trouver en fin de ligne Par d faut le mot reconnu se situe n importe o dans la ligne Notation Reconna t Codage e les lignes reconnues par e e e les lignes commen ant par un e mot reconnu par e e les lignes finissant par un e mot reconnu par e e les lignes contenant un mot e reconnu par Voici maintenant l impl mentation du module expr qui fournit l analyseur pour la syntaxe qu on vient de d crire Fichier expr ml let intervalle ci c2 let rec interv n1 n2 if n1 gt n2 then else char_of_int ni interv ni 1 n2 in interv int_of_char c1 int_of_char c2 let tous_car intervalle 000 255 308 Recherche de motifs dans un texte La fonction intervalle construit la liste de tous les caract res entre les deux c
152. les tapes importantes d une m thodologie de manipulation des donn es formelles qui nous servira dans toute la suite 9 1 Pr sentation Le but des programmes qui suivent est de simplifier encore l utilisation du crayon pour qu il puisse devenir un jeu d enfant Pour rendre le crayon utilisable par tous nous aimerions assouplir le langage du crayon de fa on 1 avoir des ordres de d placement plus explicites avancer et reculer pour les d placements tourner droite et gauche pour les changements de l angle de vis e lever et baisser la mine pour le trac 2 d finir une notion de r p tition pour viter l utilisateur du crayon la manipu lation des boucles for de Caml 3 pouvoir utiliser indiff remment des entiers ou des flottants dans les commandes du crayon pour viter les probl mes de obligatoires dans les nombres source d erreurs innombrables pour les d butants On crirait par exemple r p te 4 avance 100 droite 90 pour tracer un carr de c t 100 au lieu de l expression for i 1 to 4 do avance 100 0 tourne 90 0 done Si l on tente de d finir directement des proc dures Caml pour obtenir ces nouvelles fonctionnalit s on se heurte tr s vite des limites dues la confusion entre le langage 156 Syntaxe abstraite syntaxe concr te d impl mentation Caml et le langage impl ment celui du crayon Expliquons nous l ensemble des fonctions de manipul
153. les op rateurs sont associatifs gauche autrement dit 1 2 3 est lue comme 1 2 3 et non pas comme 1 2 3 Le reste de l analyseur syntaxique est plus simple comprendre Pour les expres sions nous introduisons un certain nombre d analyseurs interm diaires afin de re specter les priorit s usuelles entre op rateurs est plus prioritaire que and est plus prioritaire que or etc Fichier syntaxe ml let rec lire_expr0O flux match flux with lt Entier n gt gt Constante Enti re n lt MC false gt gt Constante Bool enne false lt MC true gt gt Constante Bool enne true lt Ident nom gt gt begin match flux with lt MC lire liste lire_expr el MC gt gt Application nom el lt gt gt Variable nom end lt MC lire_expr e MC gt gt e and lire_expri flux match flux with lt lire_expr0O ei gt gt match flux with lt MC lire_expr e2 MC gt gt Acc s tableau el e2 lt gt gt et and lire_expr2 function lt MC lire_expri e gt gt Op_unaire e lt MC not lire_expri e gt gt Op_unaire not e lt lire_expri e gt gt e and lire_expr3 flux lire_op ration lire_expr2 x flux and lire_expr4 flux lire_op ration lire_expr3 flux and lire_expr5 flux lire_op ration lire_expr4 lt gt lt
154. list lt fun gt Nous d finissons maintenant une fonction de lecture de programmes du langage graphique qui lit un programme dans une cha ne de caract res et rend la liste des ordres correspondants let lire_code cha ne analyse_programme analyseur_lexical stream_of_string cha ne lire_code string gt ordre list lt fun gt lire _ code r p te 4 avance 100 droite 90 ordre list Rep 4 Av Entier 100 Td Entier 90 On combine facilement la lecture et l ex cution obtenant enfin la fonction d ex cution d une cha ne de caract res recherch e let logo cha ne ex cute_programme lire_code cha ne logo string gt unit lt fun gt En guise de test imbriquons deux ordres r p te pour faire se d placer un hexagone logo ve r p te 6 td 60 r p te 6 av 15 tg 60 av 15 unit 9 7 Ajout des proc dures Dans la section pr c dente nous sommes parvenus nous lib rer de la syntaxe de Caml Malheureusement nous avons ainsi perdu la possibilit de d finir des proc dures comme nous le faisions par exemple pour dessiner les ailes d un moulin en utilisant la proc dure carr Nous allons donc tendre notre langage graphique avec une construc tion qui permette de d finir des proc dures La syntaxe abstraite des expressions du langage Avec l introduction des proc dures et de leurs param tres nous sommes oblig s d introduire la notion d exp
155. listes d association plus compliqu es que des listes cl valeur En effet nous consid rons que certains mots int ressants sont synonymes et donc que leurs r ponses associ es sont les m mes Par exemple ordinateur et machine appellent les m mes r ponses Le pluriel d un mot est souvent trait comme le mot lui m me par exemple ami et amis Dans ces listes une valeur n est donc plus associ e une seule cl mais une liste de cl s quivalentes Nous crivons donc la fonction qui teste si une cl donn e fait partie de la liste de cl s et retourne en ce cas la valeur associ e let rec associ _dans_liste cl function gt raise Pas_trouv liste_de_cl s valeur reste gt if membre cl liste_de_cl s then valeur else associ _dans_liste cl reste associ _dans_liste a gt a list b list gt b lt fun gt De la m me mani re nous avons besoin de chercher parmi une liste de cl s la valeur associ e la premi re cl qui figure dans les cl s d une liste d association listes de cl s valeur Nous parcourons donc la liste de cl s argument en cherchant l associ de la premi re cl rencontr e S il n y a pas d associ cette cl nous cherchons parmi le reste de la liste de cl s argument la premi re cl qui ait un associ dans la liste d association Remarquez au passage que le caract re est autoris dans les noms d identificateur e
156. lt Entier i gt gt Nombre i lt MC true gt gt Bool en true lt MC false gt gt Bool en false lt Ident id gt gt Variable id lt MC MC gt gt Nil lt MC expression e MC gt gt e and expr0 function lt expr_simple es suite_d applications es e gt gt e and suite_d applications f function lt expr_simple arg suite_d applications Application f arg e gt gt e lt gt gt f and expri flux lire_op ration exprO flux and expr2 flux lire_op ration expri flux and expr3 flux lire_op ration expr2 lt gt lt gt lt gt flux and expr4 flux lire_infixe expr3 fun e1 e2 gt Cons e1 e2 flux and expr5 flux lire_infixe expr4 fun e1 e2 gt Paire e1 e2 flux and d finition function lt MC let r cursive r Ident nom MC expression e gt gt r cursive r nom nom expr e and r cursive function lt MC rec gt gt true lt gt gt false and liste_de_cas function lt motif m MC gt expression e autres_cas reste gt gt m e reste and autres_cas function lt MC motif m MC gt expression e autres_cas reste gt gt m e reste lt gt gt O and motif_simple function lt Ident id gt gt Motif_variable id lt Entier
157. m tier de s occuper des machines gt gt Oui mais les langages c est encore plus rigolo Hors de Caml point de salut non gt gt Mais doit on ne parler que de Caml Sans Caml je ne serais pas l je refuse donc d en parler gt gt Mais pourquoi Ca m int resse beaucoup Il m est interdit de vous le dire gt gt Ah bon C est le programmeur qui vous en a emp ch e Moi je ne suis qu une machine gt gt Bien sympathique au demeurant Bon je crois que l exemple suffira Je vais me coucher Au revoir Cam lia Qu est ce qui vous int resse dans la vie gt gt Ca suffit Faites vous souvent des cauchemars gt gt Salut Le r sultat de mes observations Avec une probabilit de 92 37234 perversion polymorphe Au revoir Vous me devez 110 euros Ch que l ordre de Cam lia Merci unit 7 8 Pour aller plus loin Notre programme est bas sur les id es de Joseph Weizenbaum et de son syst me Eliza Communications of the ACM n 9 janvier 1966 et n 10 ao t 1967 Le but de Joseph Weizenbaum tait d explorer la compr hension que pouvait avoir un ordinateur de la conversation d un humain Eliza tait bien plus sophistiqu que notre Cam lia c tait un programme g n rique d analyse de textes et de reconnaissance de mots dans des textes qu on pouvait param trer par un domaine particulier Par exemple pour Pour aller plus loin 145 le domaine psychologique on obtena
158. mais directement des fichiers Voici par exemple la boucle d interaction qu il faut ajouter la fin du fichier logo ml pour obtenir enfin un syst me Logo ind pendant let flux_d entr e stream_of_channel std_in in let flux_lex mes analyseur_lexical flux_d entr e in while true do print_string flush std_out try ex cute_programme analyse_programme flux_lex mes with Parse_error gt print_string Erreur de syntaxe print_newline Failure s gt print_string Erreur l ex cution s print_newline done Le flush std_out qui suit l affichage du signe d invite sert garantir que l invite est bien affich e l cran avant que l on ne commence lire la prochaine phrase En effet les critures sur des canaux sont tamponn es buffered en anglais pour plus d efficacit autrement dit le syst me accumule en m moire un certain nombre d ordres d criture et les effectue en bloc plus tard En cons quence valuer print_string ne suffit pas pour assurer qu un point d interrogation appara t sur l cran il faut en plus vider to flush en anglais explicitement les critures en attente C est le r le de la fonction pr d finie flush d autres fonctions comme close_out ou print_newline vident aussi le canal de sortie Nous pouvons maintenant compiler logo ml et ex cuter le code produit camlc o logo logo ml camlrun logo Au lancement de logo to
159. mais il semble que nous ayons vraiment perdu en lisibilit par rapport la version originale Alors chec Non car il faut encore apprendre dissocier l entr e des donn es de leur valuation Nous avons r ussi crire un programme qui r alise notre plan initial en ce qui concerne la s mantique nous avons la fonction r p te d sir e et le comportement correct pour les nombres Mais nous avons chou en ce qui concerne la syntaxe c est dire l ergonomie de l criture des ordres graphiques En effet en d finissant un type de donn es Caml des ordres graphiques nous ne nous sommes pas d gag s de la syntaxe des programmes Caml Ce que nous d sirons maintenant c est crire comme bon nous semble les ordres graphiques et que cette criture agr able pour nous engendre une valeur Caml de type ordre Par exemple nous souhaitons crire r p te 3 avance 30 droite 90 mais valuer la valeur Caml Rep 3 Av Entier 30 Td Entier 90 Nous allons donc crire un programme qui r alise automatiquement cette trans formation partir d une cha ne de caract res en entr e notre programme l analysera pour produire en sortie un ordre graphique Les programmes sp cialis s dans ce genre de transformations s appellent des analyseurs syntaxiques La mani re d crire les cha nes d entr e l gales est la syntaxe concr te tandis que la valeur produite par l analyseur syntaxique est la syntaxe abstrait
160. modifiable dynamiquement ce sont les r f rences et les tableaux Les enregistrements poss dent aussi cette qualit lors de la d finition d un type enregistrement certains champs peuvent tre qualifi s de mutables c est dire modifiables Le v rificateur de type autorise alors la modification physique du contenu du champ des objets de ce type Enregistrements champs mutables Voici un exemple tr s simple o il est n cessaire de modifier des champs d enregistrement supposez qu on veuille mod liser des comptes bancaires En premi re approximation un compte se caract rise par son num ro et par le montant actuel des d p ts sur le compte le solde du compte Si le num ro du compte a peu de chance de changer en revanche le solde varie chaque retrait ou d p t Il faut donc que l tiquette solde du type compte soit d clar e mutable la d finition du type Structures de donn es mutables 119 type compte num ro int mutable solde float Le type compte est d fini La d finition d une valeur d un type enregistrement champs mutables et l acc s ses champs ne diff rent en rien du cas d un type enregistrement normal let compte _de_durand num ro 0 solde 1000 0 compte_de_durand compte num ro 0 solde 1000 0 compte_de_durand solde float 1000 0 Pour d finir la fonction d p t qui met jour le solde d un compte lors d un d p
161. mon me de P par le mon me m1 ce qui se fait simplement en multipliant les coefficients et en ajoutant les degr s En r sum let multiplie_par_mon me_creux ai degr 1 p map function a degr gt a al degr i degr p multiplie_par_mon me_creux int int gt int int list gt int int list lt fun gt let rec multiplie_polyn mes_creux pi p2 match pi p2 with CG gt fl CO D gt 0 mi restel _ gt Op rations sur les polyn mes creux 87 ajoute_polyn mes_creux multiplie_par_mon me_ creux m1 p2 multiplie_polyn mes_ creux restei p2 multiplie_polyn mes_creux int int list gt int int list gt int int list lt fun gt Nous calculons 1 X10000 titre d exemple let p 1 O0 1 10000 in imprime_polyn me_ creux multiplie _polyn mes_creux p p 1 2x 10000 x 20000 unit En premi re lecture vous en savez largement assez pour passer d s maintenant au chapitre suivant Polymorphisme et r gle n Nous devons signaler ici une petite difficult qui appara t lorsqu on utilise la r gle n pour simplifier une d finition lorsque le r sultat doit tre polymorphe Supposons que nous d finissions le tri par ordre croissant ainsi let tri_croissant 1 tri_par_insertion function x gt function y gt x lt y l tri_croissant a list gt a list lt fun gt On peut esp rer simplifier cette d finiti
162. mot Fichier lexuniv ml let rec lire_symbole position flux match flux with lt ETETE EEA IEE RS RES RES PS ef ETS ALES ET Re QE EEE ET as c gt gt if position lt string_length tampon then tampon position lt c lire_symbole position 1 flux k gt gt sub_string tampon O min position string_length tampon L analyseur lexical autorise des commentaires dans le texte d entr e sous une forme tr s simple tout ce qui suit un caract re est ignor jusqu la fin de la ligne La fonction lire_commentaire se charge de sauter tous les caract res du flux d entr e jusqu au prochain caract re de fin de ligne Fichier lexuniv ml let rec lire_commentaire flux match flux with K n gt gt O lt c gt gt lire_commentaire flux Recherche des mots cl s par hachage Ayant reconnu un mot ou un symbole il reste d terminer s il appartient la liste des mots cl s Ce test sera fait une fois pour chaque mot ou symbole du flux d entr e donc un tr s grand nombre de fois il est par cons quent crucial que ce test aille vite Au lieu d une simple recherche lin aire dans la liste des mots cl s nous employons une technique plus subtile connue sous le nom de hachage et la structure de donn es correspondante les tables de hachage La technique du hachage est d crite en d tail la prochaine section Pour l instant nous allons juste expli
163. n a pas de contenu s mantique le type figurant gauche du symbole peut tre partout remplac par le type qui figure droite Dans notre cas le type registre peut tre partout remplac par int On utilise des abr viations de type dans le but de rendre le code plus clair La simplicit du jeu d instructions de la machine se refl te dans la simplicit du type op ration il n y a que 14 op rations de base Dans les instructions ces op rations sont regroup es dans le constructeur Op puisque leurs arguments ont exactement la m me forme un registre source un op rande source un registre destination Il y a cinq formats d instructions puisque Braz et Branz ont les m mes arguments L impl mentation du module code fixe le nombre de registres 32 et donne des noms aux registres 30 sp pour stack pointer pointeur de pile et 31 ra pour return address adresse de retour Fichier code ml let nombre_de_registres 32 and sp 30 and ra 31 and taille_du_mot 4 L tat du pico processeur Le module simul impl mente le simulateur du pico processeur il fournit la fonction ex cute qui ex cute tout un programme c est dire un tableau d instructions en initialisant d abord la m moire une taille donn e Fichier simul mli open code exception Erreur of string int value lire m moire int gt int value crire _ m moire int gt int gt unit value lire_re
164. n est pas un th or me car la proposition est fausse quand P est vraie Q est fausse Le raisonnement n tait pas valide On a confondu condition n cessaire et condition suffisante une condition suffisante pour qu une proposition Q soit vraie est une propo sition P qui permet de d duire la proposition Q Autrement dit P est une condition suffisante pour que Q soit vraie si P suffit pour d montrer Q c est dire si P gt Q est vraie Sous les hypoth ses du raisonnement il est exact que P n est pas une condition suffisante pour d montrer Q En effet gt gt gt P et non Q gt non P gt Q Th or me pour toutes propositions Q P P et non Q gt non P gt Q Lois de De Morgan Nous d montrons maintenant deux th or mes bien connus en logique sous le nom de lois de De Morgan qui font le lien entre les connecteurs et ou et non gt gt gt non P et Q lt gt non P ou non Q Th or me pour toutes propositions Q P non P et Q lt gt non P ou non Q gt gt gt non P ou Q lt gt non P et non Q Th or me pour toutes propositions Q P non P ou Q lt gt non P et non Q Les lois de De Morgan sont quelquefois utiles en informatique Par exemple dans une alternative comme if not x lt 1 x gt 2 then else on simplifie la condition en employant les lois de De Morgan En effet not x lt 1 x gt 2 signifie not x lt 1 amp
165. n gt gt Motif_nombre n lt MC true gt gt Motif_bool en true lt MC false gt gt Motif_bool en false lt MC MC gt gt Motif_nil 338 Ex cution d un langage fonctionnel lt MC motif e MC gt gt e and motifi flux lire_infixe motif _simple fun mi m2 gt Motif _cons mi m2 flux and motif flux lire_infixe motifi fun mi m2 gt Motif _paire mi m2 flux let analyseur_lexical construire_analyseur function let rec in i match i yith gt n A true false wp ijas eus LD RUE ls HAL TOME PAS Mk YA UE TENS at MLJ Nils vanes NLE gt sn ess let lire_phrase f phrase analyseur _lexical f 18 Un synth tiseur de types Th se le typage est une aide importante pour le programmeur Antith se mettre les types la main dans les programmes c est lourd Synth se utilisons la synth se automatique de types PR S L INTERPR TE MINI CAML nous passons maintenant la synth se de types pour ce langage Vous apprendrez ainsi comment fonctionne le contr leur de type de Caml Cette connaissance vous permettra de mieux comprendre les erreurs de typage qu il vous signale particuli rement sur les points d licats de polymorphisme et de circularit dans les types Par dessus tout la synth se de types est un joli probl me de manipulations symboliques de donn es et de r solution de contrainte
166. nbr_arguments gt prerr_string Mauvais nombre d arguments prerr_string nom prerr_string attend prerr_int nbr_param tres prerr_string prerr_int nbr_arguments prerr_endline Tableau_attendu gt prerr_endline Acc s dans un objet qui n est pas un tableau Tableau_interdit message gt prerr_string Op ration interdite sur les tableaux prerr_string message prerr_endline affiche _ type type_r el param tre s mais est appel e avec argument s Les textes des messages d erreur sont assez descriptifs Il leur manque n anmoins une information fort utile le num ro de la ligne o l erreur s est produite Cette in formation ne figure pas dans l arbre de syntaxe abstraite Pour produire de meilleurs messages d erreur une premi re possibilit est de faire le typage en m me temps que l analyse syntaxique auquel cas on irait simplement consulter une variable globale con tenant le num ro de la ligne en cours d analyse variable tenue jour par l analyseur lexical Cette solution est simple mais complique la structure du compilateur Une autre solution plus g n rale est de travailler sur un arbre de syntaxe abstraite annot par les num ros de lignes correspondants dans le texte source Par exemple pour an noter chaque instruction il faudrait d clarer le type instruction du module syntaxe comme suit type instruction description descr_instruction ligne
167. notre interpr teur mini Camil et l allocation d une fermeture se r duit cr er une paire entre l environnement courant et l adresse de code de la fonction L autre strat gie est l allocation plat des fer metures Le compilateur cr e un tableau contenant les valeurs des variables libres du corps de la fonction Cette m thode assure que l environnement de la fermeture con tient seulement les valeurs n cessaires l ex cution de la fonction mais elle oblige recopier ces valeurs chaque cr ation de fermeture La premi re m thode partage au maximum les environnements mais tout l environnement d ex cution est mis dans la fermeture cr e Cette m thode met donc aussi le maximum de valeurs inutiles dans les fermetures occasionnant ainsi des fuites de m moires ce qui correspond la r tention de cases m moires non utilis es mais irr cup rables par le GC car toujours accessibles partir des donn es du programme dans notre cas une fermeture qui contient une donn e laquelle elle n acc dera jamais Ces fuites de m moires s av rent r dhibitoires pour certains programmes dans la mesure o elles sont imparables le programmeur n a pas les moyens de les viter puisque c est la m thode de compilation des programmes qui les engendre C est pourquoi nous pr f rons l allocation plat qui tient un plus juste compte des objets r ellement indispensables l ex cution La compila
168. nouvelle structure du mini Logo une fois qu on a ajout des interfaces tous les modules sauf le module principal 1ogo qui ne d finit rien de toute fa on Remarquez que si un type est d fini dans l interface d un module il est automatiquement d fini dans l impl mentation du module il ne faut donc pas recopier sa d finition dans cette impl mentation Compilation des interfaces Les fichiers d interface se compilent exactement comme les fichiers d impl mentation par la commande camlc c Exemple camlc c crayon mli L ex cution de cette commande cr e un fichier crayon zi contenant les d clarations de crayon mli sous une forme compil e Comme dans le cas des modules sans interface section 10 4 le fichier crayon zi est consult par le compilateur lors de la compi lation des modules qui font r f rence au module crayon De plus lorsqu on compile l impl mentation crayon ml camlc c crayon ml le compilateur v rifie la coh rence de l impl mentation avec l interface compil e crayon zi c est dire qu il v rifie que tous les identificateurs d clar s dans l interface sont bien d finis dans l impl mentation et qu ils ont bien le type annonc dans l interface C est en cela que la compilation d un module avec interface explicite diff re de la compilation d un module sans interface si l interface mli existe alors le zi est construit par compilation du mli et la compilation de l impl
169. ou Q Par exemple si nous ne nous h tons pas nous serons en retard est synonyme de h tons nous ou nous serons en retard L implication Le raisonnement si alors est appel implication en logique L implication est traditionnellement not e si P et Q sont des propositions alors par d finition P Q est une proposition qui a la m me valeur de v rit que non P ou Q La proposition P Q se lit P implique Q Nous avons maintenant d fini pr cis ment toutes les op rations de base sur les propositions Il nous reste montrer les m thodes de calcul sur ces op rations 12 2 Calculs de tables de v rit Nous commen ons par un calcul la main qui nous permettra de comprendre comment va marcher le programme de d monstration automatique Une premi re d monstration Nous allons tablir la table de v rit de l implication Plus pr cis ment nous d montrons que la proposition P Q a la table de v rit suivante PQ PQ vu uv v vj f f flv v IF v Calculs de tables de v rit 211 Nous avons d fini P gt Q comme non P ou Q ce qui signifie que ce sont les m mes propositions ou encore qu elles ont toujours la m me valeur de v rit quelles que soient les valeurs de v rit des propositions P et Q Le calcul de la table de v rit de l implication est donc tr s simple on proc de par tapes dans une table de v rit o l on a num
170. par l utilisateur let menu invites_options for i 0 to vect_length invites_options 1 do print _string lt string _of_int i gt print_string fst invites_options i print _string done print_newline print_string Choisissez votre option let r ponse read_int in snd invites_options r ponse 70 Fonctionnelles et polymorphisme menu string a vect gt a lt fun gt Ainsi la proc dure menu retourne aussi bien des entiers que des fonctions Voici par exemple un morceau de programme qui d terminerait le niveau de difficult prendre en compte dans un jeu Ici la fonction menu retourne un entier let niveau _de_ difficult print _string tes vous print _newline menu D butant 1 Amateur 7 2 Amateur confirm 5 Expert 10 l tes vous lt 0 gt D butant lt 1 gt Amateur lt 2 gt Amateur confirm lt 3 gt Expert Choisissez votre option 0 niveau_de_difficult int 1 Nous avons cependant toujours le loisir d appeler menu avec des options fonctionnelles let option menu Arr ter au_revoir Continuer continuer Ne rien faire function gt in option lt 0 gt Arr ter lt 1 gt Continuer lt 2 gt Ne rien faire Choisissez votre option 0 Au revoir unit Il est bien entendu que la fonction menu reste na ve il lui faudrait tester la validit de l
171. petit que x alors c est le plus petit de tous les l ments de la liste x reste puisque celle ci est tri e par hypoth se On place donc l ment au d but de la liste x reste let ins re l ment function O gt l ment x reste gt if l ment lt x then l ment x reste else Dans le cas contraire c est x le plus petit l ment de la liste r sultat ce r sultat sera donc x Il nous reste ins rer l ment dans la liste reste Un petit appel r cursif ins re l ment reste et le tour est jou 80 Listes let rec ins re l ment function O gt l ment x reste gt if l ment lt x then l ment x reste else x ins re l ment reste ins re a gt a list gt a list lt fun gt Il nous reste d finir effectivement la fonction de tri et l essayer let rec tri_par_insertion function D gt O x reste gt ins re x tri_par_insertion reste tri_par_insertion a list gt a list lt fun gt tri_par_insertion 3 2 1 int list 1 2 3 Synonymes dans les filtres Pour am liorer la lisibilit du code de la fonction ins re nous introduisons une facilit de nommage suppl mentaire dans les filtres Il arrive que l on veuille examiner la forme d une valeur tout en nommant cette valeur Consid rez la fonction qui rend la valeur absolue d un mon me repr sent comme un
172. position Sons let lire_lex me let rec analyseur_lexical ane Fichier asynt mli value analyse_phrase alex__lex me stream gt langage__phrase_logo and analyse_programme alex__lex me stream gt langage__programme_logo Fichier langage mli Fichier asynt ml type nombre type expression type ordre type proc dure type phrase_logo type programme_logo value ex cute_phrase phrase_logo gt unit and ex cute_programme programme_logo gt unit Fichier langage ml open crayon let flottant let ajoute_nombres x let rec valeur_expr env E let proc dures_d finies es 5 let d finit_proc dure and d finition_de let rec ex cute_ordre env let ex cute_phrase let ex cute_programme open langage open alex let rec analyse_programme and analyse_phrase and param tres and ordre and liste_d ordres and suite_d ordres and nombre and expression_simple and expression and reste_de_l expression and liste_d expressions Fichier logo ml open langage open alex open asynt let flux_d entr e in let flux_lex mes in while true do done Figure 10 2 Ajout d interfaces explicites aux modules de l interpr te mini Logo 190 Programmes ind pendants et modules Remarquez que l
173. pour nous Nous les d taillons avant d analyser le code de l addition des polyn mes creux 84 Listes 5 6 Filtrage explicite La construction match with Pour filtrer ses deux arguments en parall le la fonction d addition des polyn mes utilise un appel explicite au filtrage m canisme introduit par le mot cl match Appel explicite au filtrage match expression with filtrage Cette construction a la s mantique d une conditionnelle par cas ou encore d un if g n ralis travaillant par filtrage Red finissons la fonction nulle avec un appel explicite au filtrage on demande explicitement d examiner la forme de la liste 1 argument de nulle et l on renvoie dans chaque cas l expression ad quate let nulle 1 match 1 with D gt true _ gt false nulle a list gt bool lt fun gt On lit ce filtrage comme la phrase si la liste 1 est vide renvoyer true dans tous les autres cas renvoyer false En utilisant le filtrage explicite nous pouvons tr s facilement crire la fonction qui concat ne deux listes si la premi re liste est vide le r sultat est la deuxi me sinon il faut mettre la t te de la premi re liste devant la concat nation du reste de cette liste avec la deuxi me liste Ce qui parce que bien con u s nonce clairement ainsi let rec concat ne 11 12 match 11 with O gt 12 x reste gt x concat ne reste 12 concat ne a list
174. processeur r el est un exercice de programmation int ressant quoique difficile Bibliographie Pour une introduction progressive et tr s compl te aux architectures de processeurs on lira avec profit Architecture des ordinateurs approche quantitative de Hennessy et Patterson International Thompson Publishing 15 Compilation de mini Pascal Un mini Pascal pour une pico machine mais un programme respectable quand m me NE FOIS MA TRIS ES les techniques de l analyse syntaxique et de la ma nipulation d arbres de syntaxe abstraite il est naturel de les appliquer l impl mentation en Caml de v ritables langages de programmation Dans ce chapitre nous crivons un compilateur pour un petit langage imp ratif dans le style de Pascal mais tr s simplifi Le code produit par le compilateur est ex cutable par le simulateur du chapitre 14 C est l occasion de montrer l architecture g n rale d un compilateur et d introduire quelques algorithmes classiques de g n ration de code Ce chapitre est galement un bon exemple de structuration d un programme assez complexe 15 1 Syntaxe abstraite syntaxe concr te Le langage auquel nous allons nous int resser est un sous ensemble de Pascal Les seuls types de donn es sont les entiers les bool ens et les tableaux indices entiers Au niveau des instructions certains types de boucles ont t omis On dispose de proc dures et de fonctions mais elles ne peu
175. public Caml apporte une nouvelle approche de la programmation des plus fructueuses L investissement que vous ferez en apprenant Caml ne sera pas vain vous constaterez que le langage vous ouvre des horizons nouveaux et qu il est assez puissant pour que vous y exprimiez simplement des id es complexes Ce qui se con oit bien s nonce clairement et les programmes pour le dire vous viennent ais ment en Caml Ce livre se propose donc de faire d couvrir Caml tous ceux qui s int ressent la programmation Nous nous sommes efforc s d crire un livre accessible tout honn te homme mais qui permette cependant de ma triser le langage et d en saisir les beaut s Pour ce faire nous avons combin une introduction progressive aux principaux traits du langage avec un v ritable cours de programmation illustr de tr s nombreux exemples de programmes qui vous permettront de saisir comment on utilise Caml et de vous approprier petit petit ce merveilleux outil Les exemples vont jusqu au d veloppement de programmes complets et d une longueur respectable Nous nous effor ons de justifier ces exemples en les repla ant dans leur contexte et en analysant la clart et l efficacit xii Avant propos des solutions propos es Cet ouvrage s organise comme suit e La partie I Programmer en Caml introduit progressivement les traits du langage et les m thodes essentielles de programmation en Caml e La partie II
176. qu un seul l ment qui signifie par convention rien Nous n avons pas demand ce r sultat tout ce que nous voulions c est faire une impression un effet Mais toutes les fonctions Caml doivent avoir un argument et rendre un r sultat Lorsqu une fonction op re uniquement par effets on dit que cette fonction est une proc dure On utilise alors rien c est dire en guise de r sultat ou d argument En position d argument dans une d finition de fonction on peut consid rer comme un argument minimal l argument x auquel on aurait m me retir la variable x de m me en r sultat figure une expression parenth s e dont tout le texte aurait disparu Impressions successives s quencement Supposez qu il nous faille imprimer deux textes successifs l cran par exemple Bonjour puis tout le monde Nous devons faire deux effets la suite l un de l autre en s quence valuer en s quence deux expressions e1 et e2 signifie simplement les valuer successivement d abord e1 puis e2 Comme dans la plupart des langages de programmation la s quence est not e par un point virgule en Caml L op ration e1 puis e2 s crit donc e1 e2 Nous crivons donc print_string Bonjour print_string tout le monde Bonjour tout le monde unit La machine a d abord imprim Bonjour puis tout le monde comme on s y attendait Le r sultat de toute l op ration
177. qu un seul moyen d attribuer une s mantique au programme qu on soit en programmation s par e ou en interaction di recte avec le langage c est toujours le m me compilateur qui travaille Pour la m me raison il n y a pas de diff rence d efficacit entre programmes ind pendants et pro La compilation de Caml 367 grammes du syst me interactif compil s comme les autres les programmes d velopp s interactivement s ex cutent forc ment la m me vitesse 19 2 La compilation de Caml En point d orgue ce livre nous aurions naturellement aim vous pr senter un com pilateur pour le langage mini Caml produisant du code pour la pico machine Nous y avons renonc pour des questions de volume un tel compilateur est un assez gros pro gramme m me si la plupart des techniques introduites dans le compilateur mini Pascal s appliquent sans changements mini Caml il reste r soudre un certain nombre de difficult s propres Caml La quarantaine de pages de code et d explications n cessaires auraient rendu ce livre trop pais Dans cette conclusion nous nous contenterons de donner un aper u des probl mes nouveaux que pose la compilation de Caml et des techniques mises en uvre dans les syst mes Caml La gestion automatique de la m moire Allocation de m moire Le langage Caml n cessite des m thodes complexes de gestion de la m moire c est dire d allocation et de lib ration des adresses m moires
178. r toutes les possibilit s pour P et Q on calcule d abord la proposition non P dans tous les cas de figures puis le ou de non P et de Q On obtient finalement P Q nonP non P ouQ v v f v Lvl f f LR v v v TAKIN v Constatez que l implication est donc vraie si l hypoth se est fausse deux derni res lignes du tableau Ceci correspond l intuition lorsqu on a un th or me vrai P gt Q mais qu on n a pas l hypoth se P alors on ne peut videmment rien en d duire sur Q puisque dans ce cas Q peut aussi bien tre vraie que fausse toujours les deux derni res lignes du tableau D autre part il est impossible d attribuer une autre valeur de v rit l implication lorsque l hypoth se n est pas vraie En effet si l on mettait f la place de v dans les deux derni res lignes de la colonne de non P ou Q cela signifierait qu un th or me P Q devient faux d s que son hypoth se est fausse ce qui serait absurde On r sume parfois cette situation en disant le faux implique n importe quoi nous pr f rons la formulation on ne peut rien d duire d un th or me dont l hypoth se n est pas v rifi e ou encore un th or me reste vrai m me quand il ne s applique pas L quivalence Vous connaissez sans doute d j un autre connecteur propositionnel dont nous n avons pas parl le si et seulement si qu on appelle l
179. ros et sa somme avec un autre polyn me comprendra aussi beaucoup de z ros en g n ral consid rez par exemple 1 x 3x 1 x1 Donc dans le cas mixte nous appelons encore l addition des polyn mes creux Puisque l un des polyn mes est plein nous avons be soin d une fonction qui transforme un polyn me plein en polyn me creux C est sans 112 Les structures de donn es difficult nous parcourons le tableau des coefficients en accumulant dans une liste les mon mes rencontr s La seule subtilit est de parcourir le tableau l envers pour que le dernier mon me ajout la liste soit bien celui de degr 0 let plein_vers_creux v let 1 ref in for i vect_length v 1 downto O do if v i lt gt O then 1 v i i 1 done Il plein_vers_creux int vect gt int int list lt fun gt L addition des polyn mes se d finit alors tr s simplement let ajoute_polyn mes pi p2 match pi p2 with Plein v Plein v gt Plein ajoute_polyn mes_pleins v v Creux 1 Creux 1 gt Creux ajoute_polyn mes_ creux 1 1 Plein v Creux 1 gt Creux ajoute _polyn mes_creux plein_vers_ creux v 1 Creux 1 Plein v gt Creux ajoute _polyn mes_creux plein_vers_ creux v 1 ajoute_polyn mes polyn me gt polyn me gt polyn me lt fun gt Ce code peut tre l g rement simplifi en remarquant que les deux derniers cas du filtrage sont presque ide
180. sp d r 1 n Iposition position position taille du_mot arguments printf jmp P s ra n proc lib re_pile nbr_args If condition branche_oui Bloc gt let tiq_fin nouvelle_ tiq in compile_expr env condition 1 printf braz r 1 L d n tiq_fin compile_instr env branche_oui printf L d n tiq fin If condition Bloc branche _non gt let tiq_fin nouvelle _ tiq in compile_expr env condition 1 printf branz r 1 L d n tiq_fin compile_instr env branche _non printf L d n tiq fin If Op_unaire not condition branche oui branche non gt compile_instr env If condition branche non branche _oui If condition branche_oui branche _non gt let tiq_ non nouvelle _ tiq and tiq_fin nouvelle _ tiq in compile_expr env condition 1 printf braz r 1 L d n tiq_ non compile_instr env branche _oui printf braz r 0 L d n tiq_ fin printf L d n tiq_non compile_instr env branche_non printf L d n tiq fin While condition corps gt let tiq_ corps nouvelle tiq and tiq_test nouvelle tiq in printf braz r 0 L d n tiq test printf L d n tiq_corps compile_instr env corps printf L d n tiq test compile_expr env condition 1 printf branz r 1 L d n tiq_ corps Write expr gt compile_expr env expr 1 printf write n Read nom_var gt printf read n affecte_var env nom_var 1 299 300 Compilation
181. sultat puisque pour n 64 il aurait fallu 64 multiplications seulement La derni re version quant elle est en temps constant Elle ne n cessite que deux op rations flottantes quel que soit son argument c est l algorithme id al On retiendra qu un algorithme expo nentiel est vite susceptible d exiger un temps de calcul prohibitif quand son argument augmente Date de la fin du monde Calculons le nombre d ann es n cessaires aux moines pour achever leur jeu 64 disques Supposons qu ils puissent effectuer sans arr t jour et nuit dix mouvements par secondes ce qui est vraiment le maximum qu on puisse exiger de ces pauvres moines Il leur faudrait alors let nombre_de_mouvements_par_an nombre_de_secondes_par_an 10 0 nombre_de_mouvements_par_an float 315576000 0 compte _hanoi_ rapide 64 0 nombre de mouvements_par_an float 58454204609 1 soit plus de 58 milliards d ann es C est beaucoup plus que la dur e de vie estim e du Soleil Il semble donc que l heure de la fin du monde aura sonn tr s longtemps avant la fin du jeu Calcul de la complexit de la seconde version Dans la section pr c dente nous avons affirm que la seconde version de compte_hanoi let rec compte_hanoi function 0 gt 0 n gt 2 x compte_hanoi n 1 1 compte_hanoi int gt int lt fun gt 36 R cursivit n cessitait n multiplications La d monstration en est tr s simple
182. synonymes dans les filtres 80 117 syntaxe abstraite 159 278 289 365 syntaxe concr te 159 365 synth se de types 339 344 tableaux 40 42 65 68 75 270 terminaison 8 then 12 377 Thompson 312 Tk 193 to 39 trac de lignes 148 151 trace 23 tri 65 78 81 104 trigonom trie 150 151 true 13 try 126 128 typage 5 61 283 type 110 unification 345 353 362 unit 14 v rit tables de 209 210 v rit valeurs de 13 208 value 187 variables 7 48 variables de types 340 348 variables libres 216 variables r manentes 120 vect 40 63 vecteurs 40 vidage des canaux 183 when 121 while 39 with 84 126 128
183. syst me Caml Light puis on entre include facto ml fact int gt int lt fun gt 180 Programmes ind pendants et modules int 3628800 unit Comme on le voit sur les r ponses du syst me fact est d finie puis fact 10 valu e et le r sultat est affich Notez que le nom de fichier argument de include doit imp rativement tre mis entre guillemets c est en fait une cha ne de caract res comme les autres De plus le nom du fichier doit se terminer par l extension ml Si on donne include un nom de fichier qui ne se termine pas par ml comme dans include facto le syst me ajoute ml de lui m me et charge donc facto ml La m thode la plus pratique pour construire interactivement des programmes Caml Light est donc de faire tourner en m me temps un diteur de textes et le syst me Caml Light dans deux fen tres diff rentes on crit son code sous l diteur on l enregistre on passe Caml Light on charge le fichier avec include on lit les messages d erreur on repasse sous l diteur on corrige les erreurs on repasse Caml Light on recharge etc 10 2 Programmes ind pendants Supposons que l on veuille utiliser r guli rement le syst me Logo pr sent dans les deux chapitres pr c dents On met donc dans le fichier logo m1l toutes les d finitions n cessaires du type tat du chapitre 8 la fonction logo du chapitre 9 Pour travailler en Logo il faut alo
184. tableau l entier associ est l adresse du premier mot du bloc m moire correspondant la variable s value donc en l adresse elle m me et non pas en le mot contenu cette adresse L emplacement Global_indirect a correspond au pre mier cas une indirection partir de a est n cessaire l emplacement Global_direct a correspond au deuxi me cas pas d indirection partir de a var x integer var x array 1 3 of integer a valeur de x a valeur de x 1 le valeur de x valeur de x 2 valeur de x 3 Les variables locales des fonctions et des proc dures ainsi que leurs param tres sont stock es sur la pile Chaque fonction ou proc dure s alloue quand elle est appel e un bloc dans la pile appel bloc d activation activation record ou stack frame dans la litt rature Le bloc d activation contient les param tres les variables locales et l adresse de retour l appelant Les blocs d activation ont la structure suivante la pile cro t vers le bas 292 Compilation de mini Pascal dernier param tre premier param tre adresse de retour variables locales t temporaires pointeur de pile p Les blocs d activation s empilent les uns derri re les autres au gr des appels de fonctions et de proc dures Par exemple si g appelle f voici l tat de la pile pendant que f s ex cute adresse de retour dans g variables locales
185. tout se passe comme si on avait remplac le fichier d entr e par le fichier de sortie Toutes les fonctions d entr e sortie d clenchent l exception Sys_error du mod ule sys quand une erreur se produit avec un message explicatif en argument de l exception On intercepte donc cette exception et on affiche un message sur la sor tie d erreur standard du processus La fonction prerr_endline crit une cha ne de caract res suivie d un retour la ligne sur la sortie d erreur standard En cas d erreur on d truit le fichier de sortie s il a d j t cr et on d clenche l exception Erreur On prend bien soin de fermer les canaux quand on n en a plus besoin y compris en cas d erreurs Ce n est pas uniquement par souci d l gance les syst mes d exploitation limitent le nombre de canaux d entr es sorties simultan ment ouverts Si on oublie de fermer les canaux inutilis s on se trouve vite en situation de p nurie de canaux Nous allons maintenant utiliser deux fois la fonction traite_fichier pour d finir les fonctions de compression et de d compression d un fichier Fichier compr ml let compresse_fichier nom_fichier traite_fichier huffman__compresse nom_fichier nom_ fichier n cpr let d compresse_fichier nom_fichier let longueur string_length nom_ fichier in if longueur lt 4 sub_string nom_fichier longueur 4 4 lt gt M cpr cpr then let nom_entr e nom
186. type de tableau gr ce la pleine fonctionnalit elle s applique tout type d ordre On retrouve les proc dures de tri habituelles en sp cialisant certains param tres de la proc dure g n rale 4 6 La pleine fonctionnalit Nous avons vu que les fonctions peuvent tre pass es en arguments ou rendues en r sultat comme toutes les autres donn es Plus tonnant encore on les manipule comme des valeurs ordinaires l int rieur des structures de donn es Nous tudions maintenant un exemple qui nous am ne tr s naturellement utiliser des tableaux de fonctions Menu deux cas Notre but est d crire une fois pour toutes une proc dure qui affiche un menu lit le choix de l utilisateur et lance l option correspondante du menu Pour simplifier nous nous restreignons dans un premier temps aux menus qui offrent exactement deux possi bilit s La proc dure prend donc quatre arguments deux messages d invite afficher et deux proc dures correspondantes Apr s avoir affich le menu elle lit l option retenue par l utilisateur l aide de la fonction pr d finie read_int qui lit un entier tap au clavier puis appelle l option correspondante en testant la r ponse de l utilisateur let menu invitei optioni invite2 option2 print_string lt 0 gt invitel print_string print_string lt 1 gt invite2 print _newline print_string Choisissez votre option let r ponse read_int in
187. type_comparaison not sch ma_trivial type_fl che type_bool type_bool read_int sch ma_trivial type_fl che type_int type_int write_int sch ma_trivial type_fl che type_int type_int let boucle let env_global ref env_initial in let flux_d entr e stream_of_channel std_in in while true do print_string flush std_out try match lire_phrase flux_d entr e with Expression expr gt let ty type_exp env_global expr in print_string imprime_type ty print_newline D finition d f gt let nouvel_env type_d f env_global d f in begin match nouvel_env with nom sch ma _ gt print_string nom print_string imprime_sch ma sch ma print_newline end env_global nouvel_env with Parse_error Parse_failure gt print_string Erreur de syntaxe print_newline Conflit ty1 ty2 gt print_string Incompatibilit de types entre imprime_type ty1 print_string et imprime_type ty2 print_newline Circularit var ty gt print_string Impossible d identifier imprime_type var print_string et imprime_type ty print_newline Erreur msg gt print_string Erreur de typage print_newline LLES print_string msg done if sys__interactive then else boucle 18 8 Mise en uvre L ensemble du programme se compile par les commandes suivantes camlc c syntaxe mli camlc c types mli camlc c types ml caml
188. type_expr env function Constante Enti re n gt Integer 286 Compilation de mini Pascal Constante Bool enne b gt Boolean Variable nom_var gt cherche_variable nom_var env Application nom_fonc args gt let fonc cherche_fonction nom_fonc env in type_application env nom_fonc fonc fonc_param tres args fonc fonc_type_r sultat Op_unaire op arg gt let type_arg type_res type_op_unaire op in v rifie_type l argument de op type_arg type_expr env arg type_res Op_binaire op argi arg2 gt let type_argi type_arg2 type_res type_op_binaire op in v rifie_type le premier argument de op type_argi type_expr env argl v rifie _type le deuxi me argument de op type_arg2 type_expr env arg2 type_res Acc s _tableau expri expr2 gt let type_ l ments v rifie tableau type_expr env expri in v rifie_type l indice de tableau Integer type_expr env expr2 type_ l ments and type_application env nom param tres arguments let nbr_param tres list_length param tres and nbr_arguments list_length arguments in if nbr_param tres lt gt nbr_arguments then raise Erreur_typage Arit nom nbr_param tres nbr_arguments let type_param tre nom_param type_param argument v rifie type le param tre nom param de nom type_param type_expr env argument in do_list2 type_param tre param tres arguments and type_op_unaire function
189. un effet sur compteur pendant la d finition de g puisque l valuation de f compteur provoque l ex cution de la s quence incr x function z gt z 1 o x est li compteur On incr mente donc compteur et l on renvoie la fonction Maintenant appelons g comme pr c demment compteur int 6 g 0 int 1 compteur int 6 La valeur de compteur n est plus modifi e l appel de g En effet g a maintenant pour valeur la fonction function z gt z 1 qui ne fait bien s r aucun effet sur la valeur de compteur Par la suite les appels g n incr menteront donc plus jamais compteur Ce comportement est d l effet retard induit par les param tres de fonction quand on d finit g avec un argument explicite y il faut attendre l application de g une valeur pour commencer l ex cution du corps de g donc l valuation de f compteur y Dans le cas d une fonction d finie sans argument par un calcul les effets interviennent imm diatement puisqu il n y a aucune valeur de param tre attendre 56 Programmation imp rative 4 Fonctionnelles et polymorphisme O l on apprend qu il y a des fonctions qui fabriquent des fonctions et des types qui remplacent nimporte quoi UOIQUE R PUT ES DIFFICILES les notions de polymorphisme et de pleine fonctionnalit s introduisent tr s naturellement en Caml et vous constaterez dans ce chapitre qu elles ne sont pas
190. valeur et dont les diff rentes valeurs de v rit forment les lignes des tables de v rit Une variable est donc une proposition ind finie repr sent e par un simple nom Une variable qui intervient dans une proposition R est dite variable libre de R Par exemple P est une variable libre de la proposition P ou Q Plus pr cis ment la proposition P ou Q comporte deux variables libres P et Q Pour des raisons de commodit on a ajout deux constructeurs constants parti culiers Vrai et Faux qui repr sentent deux propositions particuli res la proposition toujours vraie et la proposition toujours fausse Ces propositions correspondent aux valeurs de v rit consid r es comme des propositions Fichier prop mli type proposition Vrai Faux Non of proposition Et of proposition proposition Ou of proposition proposition Implique of proposition proposition quivalent of proposition proposition Variable of string exception R futation of string bool list value v rifie_tautologie proposition gt string list gt unit and variables_libres proposition gt string list 214 D monstration de propositions Le module prop exporte deux fonctions v rifie tautologie qui v rifie qu une proposition est une tautologie ou sinon d clenche l exception R futation et variables_libres qui calcule la liste des variables libres d une proposition L valuateur de propositi
191. 0 t n 1 t n 1 t vect_length t 1 v La valeur retourn e par cette construction est la valeur rien q 0 lt 1 unit q int vect 1 2 2 21 r 1 lt tout r 2 lt le monde unit r string vect Bonjour tout le monde Nous savons maintenant d finir des tableaux en lire et modifier les l ments Il nous faut encore apprendre les parcourir C est tr s facile en utilisant les boucles que nous avons d crites la section pr c dente Puisqu il s agit de parcourir un tableau 42 Programmation imp rative on conna t l avance le nombre de r p titions on utilise donc une boucle pour Le parcours complet d un tableau t s effectue par une boucle commen ant en 0 et finissant en vect_length t 1 En effet puisque les indices d l ments de tableaux commencent toujours 0 le dernier l ment d un tableau a pour indice la longueur du tableau moins un Par exemple for i 0 to vect_length r 1 do print_string r i done Bonjourtoutle monde unit Pour rendre la sortie plus jolie il suffit d ajouter un blanc apr s chaque l ment for i 0 to vect_length r 1 do print_string r i print_string done Bonjour tout le monde unit Syntaxe des tableaux Pour m moire voici la syntaxe BNF correspondant ces deux constructions et la d finition des tableaux sous la form
192. 0 100000000 e Position courante d criture L criture d un bit consiste simplement le stocker dans le bit num ro nbits de val puis incr menter nbits Lorsque nbits atteint 8 on crit loctet val sur le fichier et on repart avec nbits valant 0 Fichier esbit ml let crire_bit sortie bit tampon val lt tampon val lor bit lsl tampon nbits tampon nbits lt tampon nbits 1 if tampon nbits gt 8 then begin output_char sortie char_of_int tampon val tampon val lt 0 tampon nbits lt 0 end let finir sortie if tampon nbits gt 0 then output_char sortie char_of_int tampon val Les op rateurs infixes lor et 1s1 sont respectivement le ou bit bit entre entiers et le d calage logique gauche En particulier bit 1s1 tampon nbits est un entier avec le bit num ro tampon nbits gal bit et tous les autres bits nuls La situation en cours de lecture est tr s sym trique La seule diff rence est que nbits contient maintenant le nombre de bits restant lire dans val On a marqu en gris les bits qui ont t lus par la fonctions lire_bit tampon nbits q Tampon 10011000 tampon val Fichier 11111110 10101010 00000001 110 10011 00101111 11010101 4 Position courante de lecture Fichier esbit ml let lire_bit entr e if tampon nbits lt 0 then begin tampon val lt int_of_char input_char entr e tampon nbits lt 8
193. 1 compte_ _rebours 3 compte_ _rebours lt 3 3 compte_ _rebours lt 2 compte_ _rebours lt 1 compte_ _rebours lt compte_ _rebours gt compte_ _rebours gt compte_ _rebours gt compte_ _rebours gt unit omn N peler l endroit et l envers Nous allons maintenant montrer la r cursion l uvre sur les cha nes de caract res Pour ce faire nous avons besoin d op rations suppl mentaires sur les cha nes de car act res La fonction pr d finie string_length renvoie la longueur d une cha ne de car act res La notation s i d signe le caract re de la cha ne de caract res s Le pre mier caract re a pour num ro 0 le dernier a donc pour num ro string_length s 1 Acc s dans une cha ne s s indice let le_langage Caml le_langage string Caml string_length le_langage int 4 le_langage 0 char C Un caract re en Caml est donc un signe typographique quelconque compris entre deux symboles Voici deux fonctions qui pellent des mots La premi re pelle l envers en com men ant par le dernier caract re de la cha ne et en s appelant r cursivement sur le caract re pr c dent let rec pelle_envers_aux s i if i gt 0 then begin print_char s i print _char pelle_envers_aux s i 1 end pelle_envers_aux string gt int gt unit lt fun gt
194. 1 203 205 207 207 210 212 213 217 221 223 228 232 237 237 238 240 247 252 252 255 255 260 267 275 15 Compilation de mini Pascal 15 1 15 2 15 3 15 4 Syntaxe abstraite syntaxe concr te Typage Compilation Pour aller plus loin 16 Recherche de motifs dans un texte 16 1 16 2 16 3 16 4 16 5 16 6 16 7 16 8 16 9 Les motifs Syntaxe abstraite et syntaxe concr te des motifs Les automates Des expressions rationnelles aux automates D terminisation de l automate R alisation de la commande grep Annexe Mise en pratique Pour aller plus loin III Introspection 17 Ex cution d un langage fonctionnel 17 1 17 2 17 3 17 4 17 5 17 6 Le langage mini Caml L valuateur La boucle d interaction Mise en uvre Pour aller plus loin Annexe 18 Un synth tiseur de types 18 1 18 2 18 3 18 4 18 5 18 6 18 7 18 8 18 9 Principes de la synth se de types L algorithme de synth se de types Repr sentation des types L unification Inconnues g n ralisation et sp cialisation Impression des types La boucle d interaction Mise en uvre Pour aller plus loin 19 En guise de conclusion 19 1 19 2 Index Une m thodologie de programmation La compilation de Caml Table des mati res 277 277 283 289 304 305 305 306 309 310 313 319 320 321 321 323 325 325 326 331 333 334 336 339 339 344 348 393 396 397 398 399 360 365
195. 1 62 gt 63 64 65 A 66 B 67 C 68 D 69 E 70 F 71 G 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 0 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W 88 X 89 Y 90 Z 91 92 93 94 95 _ 96 97 a 98 b 99 c 100 d 101 e 102 f 103g 104 h 105 i 106 j 107k 108 1 109m 110 n 111 0 112 p 113 q 114r 115s 116 t 117 u 118v 119w 120 x 121 y 122z 123 124 125 126 unit Le passage en minuscule revient donc un simple calcul sur le code ASCII du car act re si le caract re est une majuscule on lui ajoute 32 pour obtenir la minuscule correspondante let minuscule_de car if int_of_char car gt 65 amp amp int_of_char car lt 90 then char_of_int int_of_char car 32 else car minuscule_de char gt char lt fun gt Pour passer une cha ne de caract res tout enti re en minuscules il suffit d it rer la fonction pr c dente let minuscules cha ne let cha ne_en_minuscules create_string string_length cha ne in for i 0 to string_length cha ne 1 do cha ne_en_minuscules i lt minuscule_de cha ne i done 134 Le docteur cha ne _en_ minuscules minuscules string gt string lt fun gt Nous avons galement besoin d extraire une sous cha ne d une cha ne La sous cha ne est rep r e par ses indices de d but et de fin On utilise la fonction pr d finie sub_string qui calcule une sous cha ne partant d un indice donn et d une longueur donn e sub_string Caml O 3
196. 1 son r sultat et continuer le filtrage si cette fonction choue essayer le prochain cas du filtrage La fonction lire_lex me choue quand aucun des cas de son filtrage ne s applique c est dire quand on lui passe un flux vide Si flux est vide l appel lire_lex me choue donc et on passe au deuxi me cas de analyseur_lexical qui renvoie le flux vide Si flux n est pas vide l appel lire_lex me r ussit et extrait de flux son premier lex me la repr sentation de ce lex me transite par la variable 1 et est ajout e en t te du flux de lex mes obtenus par appel r cursif de analyseur_lexical sur le reste du flux Vous n tes toujours pas convaincu Essayons donc let flux_lex mes analyseur_lexical stream_of_string 123bonjour 45 67 flux_lex mes lex me stream lt abstr gt stream_next flux_lex mes lex me Constante_enti re 123 stream_next flux_lex mes lex me Mot bonjour stream_next flux_lex mes lex me Symbole stream_next flux_lex mes lex me Constante_flottante 45 67 Analyse syntaxique Puisque l analyseur lexical renvoie un flux de lex mes l analyseur syntaxique est une fonction qui prend en argument un flux de lex mes et le transforme en une valeur plus structur e Nous commencerons par une partie de l analyseur syntaxique qui se contente de lire un nombre soit entier soit flottant et d en faire une va
197. 8 scall O lecture d un nombre au clavier 12 jmp 100 r 31 16 scall 1 criture d un nombre l cran 20 stop L appel syst me scall O lit un nombre au clavier et le place dans r 1 Les instruc tions 0 4 et 8 lisent donc deux nombres et les placent dans les registres r 2 et r 1 L instruction 12 se branche l instruction 100 le d but du sous programme apr s avoir plac l adresse de l instruction 16 dans le registre r 31 On ex cute alors le code de la fonction moyenne arithm tique les instructions 100 et 104 calculent la moyenne der 1et der 2 et placent le r sultat dans r 1 conform ment aux conventions d appel des fonctions l instruction 108 se branche l adresse contenue dans r 31 c est dire l instruction 16 On continue donc l ex cution du programme principal affichage du registre r 1 le r sultat par l appel syst me scall 1 et arr t du programme Gestion d une pile Les conventions d appel introduites ci dessus posent probl me lorsqu un sous programme doit en appeler un autre ou se rappeler lui m me si un sous programme f appelle un sous programme g avec les conventions standard f va mettre dans r 31 une adresse de retour pour g d truisant ainsi le contenu courant de r 31 qui est l adresse de retour pour f La solution est bien s r de sauvegarder l adresse de retour pour f sur une pile La pico machine ne fournit pas d instructions push et pop pour g rer une pile mais
198. 85 Fichier alex ml Fichier langage ml open crayon type nombre let flottant type expression let ajoute_nombres let soustrait_nombres let multiplie_nombres let divise nombres let compare_nombres let rec valeur_expr env type ordre type proc dure let proc dures_d finies let d finit_proc dure and d finition_de let valeur_enti re let rec ex cute_ordre env type phrase_logo type programme_logo let ex cute_phrase let ex cute_programme Figure 10 1 D coupage en type lex me let rec saute_blancs let rec lire_entier let rec lire_d cimales Es NS let rec lire mot let lire_lex me let rec analyseur_lexical Fichier asynt ml open langage open alex let rec analyse_programme and analyse_phrase and param tres and ordre and liste_d ordres and suite_d ordres and nombre and expression_simple and expression and reste_de_l expression and liste_d expressions Fichier logo ml open langage open alex open asynt let flux _d entr e in let flux_lex mes in while true do done modules de l interpr te mini Logo 186 Programmes ind pendants et modules forme d un certain nombre de modules Par exemple la fonctio
199. At 0 End entry__insert dest At 0 printf__sprintf 2f montant _dest with Failure _ gt entry__delete_range dest At 0 End entry__insert dest At 0 erreur La fonction entry__get renvoie le texte qui figure actuellement dans un composant zone d entr e entry Ce texte peut tre modifi par le programme l aide de entry__delete_range qui efface un intervalle de caract res ici depuis At O le premier caract re jusqu End le dernier caract re effa ant ainsi tout le texte et entry__insert qui ins re la cha ne donn e en argument la position sp cifi e ici At 0 c est dire le d but de la zone let fp openTk let lignei frame__create fp and ligne2 frame__create fp l Un convertisseur de devises 197 let tiql label__create lignei Text Francs and entr e1 entry__create lignei TextWidth 10 Relief Sunken and tiq2 label__create ligne2 Text Euros and entr e2 entry__create ligne2 TextWidth 10 Relief Sunken Nous cr ons maintenant les quatre composants de notre application deux zones d entr e et deux tiquettes label qui sont des zones passives affichant un texte Pour permettre l arrangement en carr de ces composants voir figure ci dessous nous cr ons galement deux cadres ligne1 et ligne2 qui servent de composants p re tiqi et entr ei pour l un et tiq2 et entr e2 pour l autre let tauxi ref 1 0 x franc
200. C op gt mem op op rateurs 2 gt false let lire_op rateur op rateurs function lt stream_check est_un_op rateur op rateurs MC op gt gt op let lire_op ration lire_base op rateurs let rec lire_reste ei function lt lire_ op rateur op rateurs op lire_base e2 lire_reste Application Variable op Paire ei e2 e gt gt e lt gt gt ei in function lt lire_base ei lire_reste ei e gt gt e let lire_infixe lire_base infixe construire_syntaxe flux let rec lire_d but function lt lire_base e1 lire_reste e1 e2 gt gt e2 and lire_reste e1 function lt stream_check function MC op gt op infixe _ gt false _ lire_d but e2 gt gt construire_syntaxe el e2 lt gt gt ei in lire_d but flux let rec phrase function lt d finition d fin_de_ d finition d p MC gt gt p lt expression e MC gt gt Expression e and fin_de d finition d function lt MC in expression e gt gt Expression Let d e lt gt gt D finition d and expression function lt d finition d MC in expression e gt gt Let d e Annexe 337 lt MC function liste_de_cas liste gt gt Fonction liste lt MC match expression e MC with liste _de_cas liste gt gt Application Fonction liste e lt expr5 e gt gt e and expr_simple function
201. Exemples complets montre comment r soudre en Caml un certain nombre de probl mes r alistes de programmation e La partie III Introspection bauche une impl mentation de Caml en Caml expliquant ainsi le typage et l valuation de Caml En compl ment de ce livre les auteurs ont crit un second ouvrage intitul Manuel de r f rence du langage Caml et publi par le m me diteur contenant tout ce qui est n cessaire au programmeur Caml exp riment un manuel de r f rence du langage Caml et un manuel d utilisation du syst me Caml Light le compilateur Caml que nous utilisons dans ce livre Les deux livres sont con us pour tre utilis s ensemble le pr sent ouvrage renvoie au manuel de r f rence pour une description exhaustive du langage et des explications d taill es de certains points techniques le manuel de r f rence suppose connues les notions introduites dans cet ouvrage Tous les exemples de ce livre sont pr sent s dans le syst me Caml Light un en vironnement de programmation en Caml fonctionnant la fois sur micro ordinateurs Macintosh et PC et sur mini ordinateurs et stations de travail Unix Il existe d autres impl mentations du langage Caml comme par exemple Objective Caml qui ajoute Caml Light des objets et des classes ainsi qu un syst me de modules plus puissant L essentiel de ce qui est dit dans ce livre porte sur le langage et s applique donc toutes les impl mentations Nou
202. Il est clair qu on obtient la somme des l ments d une liste en appelant somme_accu avec un accumulateur valant initialement 0 let somme 1 somme_accu O 1l somme int list gt int lt fun gt somme 1 2 3 l int 6 La fonctionnelle g n rale correspondant au code de somme_accu est simplement let rec accumulateur_sur_listes f accu function OD gt accu x l gt accumulateur_sur_listes f f x accu l accumulateur_sur_listes a gt b gt b gt b gt a list gt b lt fun gt La fonction somme_accu s obtient maintenant en utilisant accumulateur_sur_listes avec l addition let somme_accu 1l accumulateur_sur_listes function x gt function accu gt x accu l somme_accu int gt int list gt int lt fun gt let somme 1 somme_accu 0 1l somme int list gt int lt fun gt somme 1 2 3 l int 6 Les fonctionnelles pr d finies en Caml sont analogues celles que nous venons de d gager avec cependant des diff rences minimes La fonctionnelle it rateur_sur_listes correspond list_it et accumulateur_sur_listes est quivalente it_list Nous d crivons maintenant ces fonctionnelles pr d finies en leur donnant une interpr tation graphique Accumuler avec les l ments d une liste tant donn s trois arguments f b et l la fonctionnelle it_list effectue de multiples compositions de la fonction deux argument
203. La fonction expr_vers_automate est alors tr s simple on construit l automate de Thompson associ l expression rationnelle on marque son tat final comme tant terminal et on renvoie l tat initial 16 5 D terminisation de l automate Ayant obtenu un automate qui reconna t les m mes cha nes que l expression ra tionnelle de d part il nous reste programmer une fonction qui teste si une cha ne est reconnue ou non par l automate Ce test n est pas imm diat en g n ral puisque plusieurs transitions portant le m me caract re peuvent sortir d un m me tat il faut quelquefois essayer plusieurs chemins qui pellent la cha ne reconna tre Cependant il existe une classe d automates les automates d terministes pour lesquels le probl me est beaucoup plus simple Un automate d terministe a les deux propri t s suivantes 1 il ne poss de pas de transition marqu e 2 d un m me tat il ne part jamais plusieurs transitions marqu es par le m me caract re Voici par exemple deux automates d terministes reconnaissant le la les pour celui de gauche et les entiers en base deux pour celui de droite Pour tester si une cha ne est reconnue par un automate d terministe il suffit de partir de l tat initial et de suivre chaque tat la transition unique marqu e par le prochain caract re de la cha ne Si on aboutit sur un tat terminal la cha ne est reconnue Si on aboutit s
204. Not_found gt Ident ident Une variante de mc_ou_ident nous sera utile pour reconna tre les mots cl s mono caract res par exemple les parenth ses Fichier lexuniv ml let mc_ou_erreur table_des_mots_cl s caract re let ident make_string 1 caract re in try hashtbl__find table_des_mots_cl s ident with Not_found gt raise Parse_error Pour aller plus loin l analyseur lexical universel 231 Reconnaissance d un lex me La lecture des lex mes consiste tout d abord passer les blancs et les commentaires puis reconna tre un identificateur un mot cl ou un nombre entier ventuellement n gatif donc pr c d du signe Les symboles mono caract res comme les par enth ses 1 ou bien les caract res non imprimables doivent tre d clar s comme mots cl s sinon ils produisent une erreur Fichier lexuniv ml let rec lire_lex me table flux match flux with PER ECS of RE UNE I NEO ST gt lire_lex me table flux lt gt gt lire_commentaire flux lire_lex me table flux L ie CAs VAE tati s a fa dea jee da l l a l il lc A O AEEA O EI Gg as c gt gt tampon 0 lt c mc_ou_ident table lire_mot 1 flux lt CILESIA RE EEA GES ONE a aa C E a A a ETS as c gt gt tampon 0 lt c mc_ou_ident table lire_symbole 1 flux lt 0 9 as c gt gt Entier lire_entier int_of_char c 48 flux lt
205. Nous noterons Op compte_hanoi n le nombre d op rations n cessaires pour effectuer le calcul de compte_hanoi n l aide de cette version de compte_hanoi Nous d montrons par r currence la propri t P n d finie par P n est vraie si et seulement si Op compte_hanoi n n La propri t P 0 est vraie car Op compte_hanoi 0 0 Supposons P n vraie et montrons qu alors P n 1 est vraie Pour montrer P n 1 il faut d montrer Op compte_hanoi n 1 n 1 Or d apr s le code de la fonction compte_hanoi quand on a le r sultat de compte _hanoi n 1 il faut faire une multiplication de plus pour obtenir compte_hanoi n On a donc Op compte_hanoi n 1 1 Op compte_hanoi n mais d apr s l hypoth se de r currence Op compte_hanoi n n et donc Op compte_hanoi n 1 n 1 Il s ensuit que P n est vraie pour tout n Remarquons pour finir que nous avons calcul la complexit de hanoi en utilisant la fonction compte_hanoi dont nous avons d nouveau tudier la complexit pour l optimiser sous peine de ne pas obtenir effectivement la complexit de hanoi Il faut d cid ment r fl chir sur les programmes qu on crit 3 Programmation imp rative O l on apprend que 2x 2x font 4x i OUS METTONS EN PLACE dans ce chapitre quelques outils indispensables la pro grammation imp rative En particulier nous introduisons la notion de tableau et l utilisons pour calc
206. Pierre Weis Xavier Leroy LE LANGAGE CAML Deuxi me dition Copyright 1992 1993 2009 Pierre Weis et Xavier Leroy Ce texte est distribu sous les termes de la licence Creative Commons BY NC SA Le texte complet de la licence est disponible l adresse suivante http creativecommons org licenses by nc sa 2 0 fr legalcode Voici un r sum des droits et conditions de cette licence e Vous tes libres de reproduire distribuer et communiquer cette cr ation au public de modifier cette cr ation e Selon les conditions suivantes Paternit Vous devez citer le nom de l auteur original de la mani re indiqu e par l auteur de l oeuvre ou le titulaire des droits qui vous conf re cette autorisation mais pas d une mani re qui sugg rerait qu ils vous soutiennent ou approuvent votre utilisation de l oeuvre Pas d Utilisation Commerciale Vous n avez pas le droit d utiliser cette cr ation des fins commerciales Partage des Conditions Initiales l Identique Si vous modifiez transformez ou adaptez cette cr ation vous n avez le droit de distribuer la cr ation qui en r sulte que sous un contrat identique celui ci e chaque r utilisation ou distribution de cette cr ation vous devez faire ap para tre clairement au public les conditions contractuelles de sa mise disposition La meilleure mani re de les indiquer est un lien la page Web ci dessus e Chacune de ces
207. S s 2 Q A Il N 2 EF D a fu n 3 nan a di A0 did id id ia i D Listes La t te et la queue sans les oreilles ARMI LES STRUCTURES DE DONN ES PR D FINIES en Caml les listes ont un statut privil gi elles sont d emploi fr quent car simples manipuler et tr s g n rales Si vous savez que les listes peuvent peu pr s tout coder mais qu il ne faut pas pour autant les mettre toutes les sauces en bref si vous connaissez bien it_list et que justement vous vitez de l employer trop souvent alors lisez directement le chapitre suivant Nous verrons dans celui ci une autre repr sentation des polyn mes par des listes de paires d entiers et nous animerons le jeu des tours de Hano en montrant l volution de l tat du jeu Au passage nous approfondirons le filtrage appel explicite au fil trage synonymes dans les filtres filtrage multiple et nous verrons des exemples de fonctionnelles sur les listes 5 1 Pr sentation Syntaxe Les listes sont des suites homog nes de valeurs entour es de crochets et Comme pour les tableaux les l ments des listes sont s par s par un point virgule 1 2 3 int list 1 2 3 Au contraire des tableaux on n acc de pas directement un l ment de liste il faut parcourir s quentiellement la liste pour atteindre l l ment recherch En revanche les listes peuvent grossir dynamiquement alor
208. _crayon unit gt unit lt fun gt Ce n est pas parfait car on oblige encore l utilisateur taper baisse_le_crayon pour baisser le crayon Cette paire de parenth ses obligatoire n est pas vidente pour tout le monde La grande difficult est la fonction r p te On aimerait fournir r p te un nombre de r p titions effectuer et une liste d ordres graphiques r p ter par exemple r p te 4 avance 50 0 tourne 90 0 Na vement on d finirait let r p te n 1 for i 1 to n do 1 done r p te int gt a gt unit lt fun gt Malheureusement la liste 1 des ordres est compl tement valu e et donc les ordres qu elle contient sont ex cut s au moment de l appel de la fonction r p te Dans le corps de r p te on ne fait que relire une liste de valeurs rien ce qui n a pas grand effet Le retard l valuation 157 r p te 4 print_int 1 print_char l 1 unit Le 1 s affiche avant l ex cution de la boucle qui elle n affiche rien du tout puisqu elle ne fait qu valuer quatre fois de suite la liste de riens O O1 r sultat de l valuation du deuxi me argument de r p te D ailleurs le type de r p te aurait pu nous mettre la puce l oreille int gt a gt unit met bien en vidence que r p te n utilise pas vraiment son argument 1 la liste des ordres puisque cet argument n est finalement soumis aucune contrainte pas m
209. _fichier M and nom_sortie nom_fichier in traite_fichier huffman__d compresse nom_entr e nom_sortie else let nom_entr e nom_fichier and nom_sortie sub_string nom_fichier O longueur 4 in traite_fichier huffman__d compresse nom_entr e nom_sortie Dans le cas de la d compression le nom du fichier compress peut tre donn avec 240 Compression de fichiers ou sans l extension cpr Si le nom fourni ne se termine pas par l extension cpr c est en fait le nom du fichier de sortie on lui ajoute cpr pour obtenir le vrai nom du fichier d entr e Si le nom fourni se termine par l extension cpr on l enl ve par un sub_string bien calcul pour obtenir le nom du fichier de sortie Les deux fonctions huffman__compresse et huffman__d compresse proviennent du module huffman que nous tudierons en d tail dans la prochaine section Pour l instant contentons nous de l interface de ce module Fichier huffman mli value compresse in_channel gt out_channel gt unit and d compresse in_channel gt out_channel gt unit Le point d entr e dans le programme reconna t l option d et applique bon escient les fonctions compresse_fichier ou d compresse_fichier chaque argument fourni sur la ligne de commande Les arguments donn s une commande sont accessibles dans le tableau de cha nes de caract res command_line du module de biblioth que sys L l ment d indice z ro contient
210. _proc dure in let variables d finition param tres and corps d finition corps in let rec augmente_env function 0 gt env variable vars expr exprs gt variable valeur_expr env expr augmente_env vars exprs gt failwith mauvais nombre d arguments pour nom_de_proc dure in let env_pour_corps augmente_env variables args in try do_list ex cute_ordre env_pour_corps corps with Fin_de_proc dure gt ex cute_ordre string nombre list gt ordre gt unit lt fun gt L ordre Si est tr s simple si la comparaison des deux expressions renvoie vrai on ex cute la partie alors et dans le cas contraire on ex cute la partie sinon Remarquez que la fonction ex cute_ordre est appliqu e partiellement lenvironnement courant c est la fonction ainsi obtenue qui est appliqu e tous les ordres de la liste choisie do_list ex cute_ordre env alors L ordre Stop est ex cut en d clenchant lexception Fin_de_proc dure qui inter rompt donc brutalement lex cution de la liste d ordres constituant le corps d une proc dure Cette exception est videmment surveill e par l ex cution du corps de toute proc dure si elle survient elle est alors rattrap e et la proc dure est consid r e comme termin e c est le try with qui appara t dans la clause concernant Ex cute L valuation d un ordre Ex cute consiste d abord obtenir la d finition de la proc d
211. a list gt int lt fun gt list_length 0 3 5 7 l int 4 On crit de m me la concat nation des listes l aide d une fonction auxiliaire devant qui recopie une liste devant une autre let rec devant 12 function gt 12 x l1 gt x devant 12 l devant a list gt a list gt a list lt fun gt devant 4 5 6 1 2 3 int list 1 2 3 4 5 6 let concat ne 11 12 devant 12 11 concat ne a list gt a list gt a list lt fun gt La fonction devant suit galement le m me sch ma avec l ment de base 12 et op ration let devant 12 it rateur_sur_listes function x gt function y gt x y 12 devant a list gt a list gt a list lt fun gt devant 4 5 6 1 2 3 int list 1 2 3 4 5 6 Notion d accumulation r cursive Un autre sch ma r cursif qui revient souvent est l accumulation Par exemple pour crire la fonction somme il est naturel d ajouter les l ments de la liste un accumula teur qu on rendra en r sultat quand on arrivera la fin de la liste Nous sommes donc amen s crire la fonction somme_accu suivante qui accumule les l ments d une liste dans son accumulateur argument accu let rec somme_accu accu function D gt accu x l gt somme_accu x accu l somme_accu int gt int list gt int lt fun gt 94 Listes
212. a machine sur un fichier de code pr alablement assembl on se contente de lire ce code en m moire puis de lancer la fonction ex cute Pour simplifier la lecture du code machine nous allons utiliser les fonctions d entr e sortie structur e que fournit le syst me Caml Light La fonction pr d finie output_value qui a pour type out_channel gt a gt unit crit une repr sentation de son argument une valeur Caml quelconque sous forme d une suite d octets sur le canal sp cifi La fonction input_value effectue l op ration inverse elle lit une suite d octets sur un canal et renvoie la structure Caml correspondante Ces deux fonctions nous ont d j servi pour sauvegarder des arbres de Huffman la section 13 3 266 Simulation d un processeur Le point d entr e de la commande analyse les arguments fournis par l utilisateur pour d tecter la pr sence d un entier fixant la taille m moire utiliser sinon on lance la machine avec une taille de 1K mots On surveille aussi les exceptions qui pourraient se produire pour afficher un message et rendre un code d erreur ad quat Fichier exec ml open code open simul exception Fichier_incorrect let ex cute_fichier nom_fichier taille m moire let canal open_in_bin nom_fichier in let programme try input_value canal instruction vect with Failure _ gt raise Fichier_incorrect in close_in canal ex cute programme taille_m mo
213. a r ponse de l utilisateur et l interroger nouveau en cas d erreur La validation de la r ponse pourrait s effectuer l aide d une fonction argument suppl mentaire de menu On peut aussi envisager de lire des cha nes de caract res au lieu de nombres par exemple oui ou non Il n en demeure pas moins que le polymorphisme et la pleine fonctionnalit nous permettent d crire une fonction tr s g n rale dans laquelle les probl mes de mise en page des menus d obtention d une r ponse et de validation de la r ponse obtenue seront factoris s une fois pour toutes Vous en savez maintenant assez pour passer au chapitre suivant Ce qui suit est tonnant mais technique En particulier nous verrons que le langage est assez puissant pour d finir un moyen automatique de passer de la version curryfi e la version non curryfi e d une fonction 4 7 Composition de fonctions En utilisant des fonctionnelles on parvient programmer des notions math matiques qui paraissent a priori hors de port e d une machine Pour les lecteurs f rus de math matiques nous allons tudier un exemple surprenant la composition des fonc tions Il est non seulement possible de d finir la composition de deux fonctions donn es en Caml mais m me d crire un programme qui impl mente le fameux op rateur o Rappelons que composer deux fonctions revient les appliquer successivement la compos e des fonctions f et g qu on not
214. ac ceptables n est pas tr s claire Certains syst mes Caml autorisent la d finition r cursive de listes boucl es let rec x 1 x Dans le cas des langages paresseux on montre qu il est toujours possible de traiter une d finition r cursive par it ration d une fonction partir de la valeur ind fini voyons l id e qui sous tend ce m canisme avec la d finition de la fonction factorielle On construit d abord la fonction repr sentant l ind fini et la fonction phi dont on cherche un point fixe let ind fini x failwith ind fini ind fini a gt b lt fun gt let phi f function x gt if x 0 then 1 else x f x 1 phi int gt int gt int gt int lt fun gt Puis on d finit les it rations successives de phi en partant de la valeur ind finie let fact0 phi ind fini factO int gt int lt fun gt let facti phi factO facti int gt int lt fun gt let fact2 phi fact1 fact2 int gt int lt fun gt let fact3 phi fact2 fact3 int gt int lt fun gt Les fonctions fact0 fact1 fact2 et fact3 sont des approximations successives de la fonction factorielle de plus en plus d finies c est dire d finies sur un nombre croissant d entiers Argument factO facti fact2 fact3 0 1 1 1 1 1 ind fini 1 1 1 2 ind fini ind fini 2 2 3 ind fini ind fini ind fini 6 Dans un langage paresseux les d fini
215. act o 10 3628800 Si l on a compil et charg les modules depuis le syst me interactif le m me r sultat s obtient par les commandes asm__assemble_fichier fact asm fact o et exec__ex cute_fichier fact o 4096 Pour aller plus loin 275 Adresse Instruction Assembleur source Le programme principal 0 Scall 0 read 4 Jmp Im 16 31 jmp fact ra 8 Scall 1 write 12 Stop stop La fonction fact N 16 Braz 1 60 fact braz r 1 factO 20 Op Sub 30 Imm 8 30 sub sp 8 Sp 24 Op Store 30 Imm O 31 store sp 0 ra 28 Op Store 30 Imm 1 1 store sp 4 r 1 32 Op Sub 1 Imm 1 1 sub ri i ri 36 Jmp Imm 16 31 jmp fact ra 40 Op Load 30 Imm 1 2 load sp 4 r 2 44 Op Mult 1 Reg 2 1 mult ri r2 ri 48 Op Load 30 Imm 0 31 load sp 0 ra 52 Op Add 30 Imm 8 30 add sp 2 sp 56 Jmp Reg 31 0 jmp ra ro 60 Op Add O Imm 1 1 fact0 add ro 1 ri 64 Jmp Reg 31 0 jmp ra r 0 Figure 14 3 R sultat de l assemblage du fichier fact asm titre d exemple nous donnons figure 14 3 le code assembl par la commande pico_asm pour le fichier fact asm page 268 en faisant figurer en regard de chaque instruction assembl e le code source correspondant du fichier On constate sur cet exemple que les tiquettes ont t r solues correctement et que le registre sp est bien expans en son num ro absolu 14 4 Pour aller plus loin Le mod le de pico processeur que nous avons d
216. aie si P et Q sont toutes les deux vraies Nous venons de le voir P ou Q est vraie 210 D monstration de propositions d s que l une des propositions est vraie si les deux propositions P et Q sont vraies P ou Q est a fortiori vraie on serait tent de dire encore plus vraie puisqu il y a deux raisons pour qu elle soit vraie La difficult vient de ce que l emploi de ou dans la langue commune n est pas toujours celui l En r alit la s mantique du ou dans la langue parl e est assez floue Consid rez les phrases suivantes Fromage ou dessert D fense de fumer ou de cracher Mange ta soupe ou tu auras une fess e Dans fromage ou dessert le ou est exclusif on aura du fromage ou bien du dessert mais pas les deux En revanche le ou de fumer ou cracher a le sens des math matiques il est inclusif En effet il est interdit de fumer il est interdit aussi de cracher mais il est encore plus interdit de cracher tout en fumant Finalement le ou de mange ta soupe ou tu auras une fess e a le sens d une d duction on pourrait le remplacer par sinon mange ta soupe sinon tu auras une fess e C est le sens aussi d un si alors si tu ne manges pas ta soupe alors tu auras une fess e Cette signification particuli re du ou n est pas un hasard c est au contraire l exacte d finition math matique de l implication Le raisonnement si P alors Q est synonyme de non P
217. ait t accept e ins rant un entier dans la m me liste Cela aurait videmment invalid l hypoth se fondamentale que les listes sont homog nes Cependant si le contr leur de type avait suivi les r gles habituelles cette g n ralisation aurait d avoir lieu comme dans lexemple similaire sans r f rences let y in let z true y in Tai ys int list 1 De nombreux algorithmes ont t propos s pour typer les valeurs mutables Tous tentent viter la cr ation de valeurs mutables polymorphes en restreignant le poly morphisme au niveau de la construction let Nous n tudierons pas ces algorithmes qui ne sont pas simples et sans doute pas encore d finitifs Il existe cependant une m thode tr s simple permettant de r gler ce probl me elle consiste changer l algorithme de base bien entendu au niveau du typage du let en d cidant que toutes les expressions ne sont pas g n ralisables on ne g n ralise que les constantes les variables et les fonctions imm diates La preuve de correction de cet algorithme pour les valeurs mutables est facile apporter il n y a jamais de cr ation de valeurs mutables polymorphes puisque le polymorphisme est r serv des expressions qui ne peuvent pas cr er de valeurs mutables C est en effet clair pour les constantes et les variables Pour les fonctions imm diates c est aussi vident ces fonctions sont celles directement introduites par le mot cl
218. am lt abstr gt lire_lex me flux_car lex me Constante_ enti re 123 lire_lex me flux_car lex me Mot bonjour lire_lex me flux_car lex me Symbole lire_lex me flux_car lex me Constante_flottante 45 67 Pour finir il reste construire le flux des lex mes lus let rec analyseur_lexical flux match flux with lt lire _lex me 1 gt gt lt l analyseur _lexical flux gt lt gt gt lt gt analyseur_lexical char stream gt lex me stream lt fun gt Cette fonction utilise deux nouvelles op rations sur les flux Premi rement l ajout d un l ment x en t te d un flux f se note lt x f gt sans apostrophe devant le f De m me la concat nation de deux flux f et f se note lt f1 f2 gt sans apostrophes du tout Le point virgule l int rieur des crochets pointus peut se lire comme l op rateur de concat nation de flux l apostrophe comme l op rateur qui prend une valeur x et renvoie le flux un seul l ment x Autre op ration nouvelle sur les flux on peut lors d un filtrage sur un flux appeler une fonction d analyse depuis l int rieur du motif Ceci se note lt lire_lex me 1 gt sans apostrophe avant lire_lex me et signifie appliquer la fonction lire_lex me 166 Syntaxe abstraite syntaxe concr te au flux en cours de filtrage ici flux si cette fonction r ussit appeler
219. anc Rouge Le type peinture est d fini Les trois constructeurs sont maintenant trois nouvelles constantes du langage Caml de type peinture let p Bleu p peinture Bleu Tout naturellement le filtrage s applique aussi ce nouveau type let est_blanche function Blanc gt true _ gt false est_blanche peinture gt bool lt fun gt est_blanche p bool false Ces types somme ne comportant que des constantes sont appel s types num r s Vous en connaissez d j par exemple le type bool est un type somme num r deux constantes true et false 114 Les structures de donn es Types constructeurs non constants Nous supposons maintenant qu il existe dans l ensemble de toutes les peintures des teintes qui n ont pas de nom mais seulement un num ro de r f rence Nous tendons donc le type peinture avec un nouveau constructeur qui prenne en compte ce cas Il s agit maintenant d un constructeur ayant un argument le num ro de r f rence Appelons ce constructeur Num ro Par exemple Num ro 14 mod lisera la peinture de r f rence num ro 14 Nous d finissons donc le nouveau type des peintures comme type peinture Bleu Blanc Rouge Num ro of int Le type peinture est d fini Types r cursifs La prochaine tape est la description des m langes de peintures Il existe maintenant des peintures qui sont simplement des m langes de deux autres pein
220. ant d une r f rence est renvoy par l op rateur de d r f rencement c est dire de lecture d une r f rence not Il ne faut pas confondre cette notation avec l op rateur factorielle des math matiques que nous avons vu au chapitre 2 et qui se place apr s son argument le Caml se place avant son argument 48 Programmation imp rative compteur int 0 compteur 4 0 On change le contenu d une r f rence criture en utilisant le symbole traditionnel de l affectation compteur 2 unit L affectation est graphiquement l op ration inverse de compteur 2 Apr s l affectation le contenu de la bo te compteur est donc 2 compteur int 2 Pour incr menter compteur nous devons ajouter 1 au contenu courant de la bo te compteur 1 compteur unit compteur int 3 Une r gle g n rale en Caml est que tous les objets du langage sont manipulables comme des valeurs sans restrictions particuli res on les passe en param tre et on les rend en r sultat au m me titre que les valeurs de base Les r f rences ne d rogent pas cette r gle Nous pouvons donc passer des r f rences en param tre et d finir une proc dure qui incr mente le contenu de n importe quelle r f rence contenant un entier cette proc dure est pr d finie sous le nom incr dans le syst me Caml mais nous en
221. ant de Caml Light Entr es sorties de base 181 tourne donc sous un interpr te de commandes appel MPW Macintosh Programmer s Workshop et disponible gratuitement aupr s d Apple Les lecteurs qui disposent d un Macintosh mais qui n ont pas MPW ne peuvent pas utiliser le compilateur ind pendant la section 10 6 explique comment proc der en utilisant seulement le syst me interactif Nous supposons que l interpr te de commandes a le symbole pour signe d invite Les lignes qui commencent par consistent donc en des commandes entr es par l utilisateur Les autres lignes sont les messages qu affichent les commandes pendant qu elles s ex cutent On compile le fichier hello ml l aide de la commande camlc o hello hello ml Cette commande signifie mettre dans le fichier hello le code compil pour les phrases Caml contenues dans le fichier hel1o m1l S il n y a pas d erreurs elle se d roule sans rien afficher Pour ex cuter le code produit il faut lancer la commande camlrun hello Bonjour tout le monde Le programme a ex cut les trois phrases qui le composent dans l ordre puis a rendu la main Rien d autre ne s affiche contrairement ce qui se passe en utilisation inter active le syst me n crit pas de lui m me le type et la valeur de chaque phrase Dans un programme ind pendant si l on veut faire afficher un r sultat il faut le faire ex plicitement en appelant une fonct
222. appelons pack cinq fois pour r aliser l arrangement en carr des composants d crit par la figure ci dessus puis lan ons la boucle d interaction Choix des devises par un menu Il n est pas difficile d tendre notre convertisseur d autres devises que le franc et l euro Pour ce faire nous ajoutons deux menus d roulants permettant de choisir les devises source et cible de la conversion let barre _de_ menus frame__create fp Relief Raised BorderWidth Pixels 2 let bouton_source menubutton__create barre_de_menus Text Source UnderlinedChar 0 and bouton_cible 198 Interfaces graphiques menubutton__create barre_de_menus Text Cible UnderlinedChar Ol let source menu__create bouton_source and cible menu__create bouton_cible l menubutton__configure bouton_source Menu source menubutton__configure bouton_cible Menu cible pack bouton_source bouton_cible Side Side Left La barre de menus se compose d un cadre barre_de_menus de deux boutons menus bouton_source et bouton_cible dont l effet est de d rouler les menus cor respondants et enfin de deux composants de type menu source et cible qui contiennent les entr es des menus Les menus sont pour l instant vides nous allons les remplir dans le code qui suit let liste_de_ devises Dollars US 5 9389 Dollars canadiens 3 933046 Euros 6 55957 Francs 1 0 Francs belges 0 162531 F
223. ar act res donn s Elle sert pour l expansion des classes de caract res La liste tous_car est la liste des 256 caract res du code ASCII Elle sert pour l expansion de la construc tion en la classe de tous les caract res L essentiel de l analyse syntaxique est effectu par le groupe de fonctions mutuelle ment r cursives ci dessous La syntaxe d entr e est si primitive que nous n avons pas besoin d une phase pr alable d analyse lexicale Le d coupage en plusieurs fonctions interm diaires assure en particulier que les priorit s entre op rateurs sont respect es Fichier expr ml let rec lire_expr function lt lire_s q ri lire_alternative r1 r2 gt gt r2 and lire_alternative ri function lt lire_expr r2 gt gt Alternative r1 r2 lt gt gt r1 and lire_s q function lt lire_r p t ri lire_fin_s q ri r2 gt gt r2 and lire_fin_s q ri function lt lire_s q r2 gt gt S quence r1 r2 lt gt gt ri and lire_r p t function lt lire_simple r1 lire_fin_r p t r1 r2 gt gt r2 and lire_fin_r p t ri function lt x gt gt R p tition ri lt f gt gt S quence r1 R p tition ri lt 7 gt gt Alternative r1 Epsilon lt gt gt ri and lire_simple function lt gt gt Caract res tous_car lt f lire_classe cl gt gt Caract
224. ar s par des Notre polyn me p xz 2z 3 se d finit donc par la phrase let p 3 2 1 l p int vect 13 2 11 Graphiquement on repr sente naturellement les tableaux par une succession de cases Par exemple p sera repr sent ainsi Manipulation de polyn mes 41 O Co N N indices Pour construire des tableaux dont on remplira les cases plus tard on dispose de la fonction pr d finie make_vect Avec cette fonction on cr e un tableau en donnant sa taille et un l ment qui sera mis au d part dans toutes les cases du tableau la valeur d initialisation du tableau D finissons par exemple un tableau de taille 4 contenant des 2 et un tableau de taille 3 contenant la cha ne Bonjour let q make_vect 4 2 q int vect 2 2 2 21 let r make_vect 3 Bonjour r string vect l Bonjour Bonjour Bonjour La taille d un tableau s obtient en appelant la primitive vect_length vect_length q int 4 Une fois le tableau cr on peut consulter et modifier le contenu de ses cases Si t est un tableau et n un entier t n d signe l l ment d indice n du tableau t t t 0 t n t vect_length t 1 let a0 p 0 a0 int 3 On affecte la valeur v la case n du tableau t par la construction t n lt v Cela correspond graphiquement t t
225. ar exemple la limite quand n tend vers l infini de f n ce qu on note en math matiques lim f n et qui signifie la valeur de f n quand n devient arbitraire ment grand existe ventuellement en math matiques mais ne peut qu tre approch e par une machine Enfin l valuation des expressions d un langage de programmation tel que Caml ne termine pas toujours les calculs peuvent boucler et donc ne jamais s achever Autrement dit les fonctions d finissables par un programme sont en g n ral des fonctions partielles non d finies pour certaines valeurs plut t que des fonctions totales toujours d finies D finitions locales Les d finitions de noms que nous venons de voir sont permanentes elles restent valides tant que vous n abandonnez pas le syst me Caml Ces d finitions d finitives sont qualifi es de globales Cependant pour faire un petit calcul il est inutile d utiliser des d finitions globales on dispose donc en Caml d un moyen de d finir temporairement des noms pour la seule dur e du calcul en question Ces d finitions temporaires sont les d finitions locales qui disparaissent la fin de l valuation de la phrase dans laquelle elles se trouvent Ces d finitions locales ne sont donc plus valides apr s le calcul de l expression qui les suit apr s le mot cl in qui signifie dans let s 20 in s 4 int 80 Le nom s a t li 20 pendant le calcul de s 4
226. arge la valeur de argi dans un registre temporaire le registre 29 Compilation des instructions On passe maintenant la compilation d une instruction La plupart des cas sont similaires ceux de la compilation d une expression Fichier compil ml let compteur_d tiquettes ref 0 let nouvelle _ tiq incr compteur_d tiquettes compteur_d tiquettes let rec compile_instr env function Affectation_var nom_var Constante Enti re 0 Bool enne false gt affecte_var env nom_var 0 Affectation_var nom_var expr gt compile_expr env expr 1 affecte_var env nom_var 1 Affectation_tableau expr1 Constante cst2 expr3 gt let inf sup type_ l ments type_de_tableau env expr in let reg3 reg1 compile_arguments env expr3 expri 1 in printf store r d 4 r d n regi val_const cst2 inf taille_du_mot reg3 Affectation_tableau expr1 expr2 expr3 gt let inf sup type_ l ments type_de_tableau env expri in compile_expr env expr3 1 let reg1 reg2 compile_arguments env expri expr2 2 in if inf lt gt 0 then printf sub r 44 d r d n reg2 inf reg2 printf mult r d d r d n reg2 taille_du_mot reg2 Compilation printf store r 44 r d r d n regi reg2 1 Appel proc arguments gt let nbr_args list_length arguments in r serve_pile nbr_args let position ref 0 in do_list function arg gt compile_expr env arg 1 printf store
227. assembleur Enfin il enrichit et rend plus uniforme le jeu d instructions de la machine en ajoutant des pseudo instructions qui se pr sentent ex actement comme des instructions de la machine mais sont en fait expans es en une ou plusieurs vraies instructions Par exemple notre assembleur sait coder les compara isons sup rieur et sup rieur ou gal instructions sgt et sge qui sont initialement absentes du jeu d instructions Voici par exemple un fichier d assembleur de la pico machine crit la main et qui programme la fonction factorielle Fichier fact asm Le programme principal read lecture de l argument dans r 1 jmp fact ra calcul de la factorielle write criture du r sultat r 1 stop La fonction factorielle N L argument N est dans r 1 Le r sultat est mis dans r 1 fact braz r 1 fact_O N 07 sub sp 8 Sp r serve deux places dans la pile store sp 0 ra sauvegarde de l adresse de retour store sp 4 r 1 et de la valeur de N sub rois its jmp fact ra appel r cursif sur N 1 load sp 4 r 2 r cup ration de la valeur de N mult ri r 2 r 1 calcul de N fact N 1 load sp 0 ra r cup ration de l adresse de retour add sp 8 Sp et de la place en pile jmp ra r 0 retour l appelant fact_0O add 1 0 i mettre 1 dans ri jmp ra r 0 retour l appelant On a crit simplement jmp fact ra en utilisant l tiquette symb
228. at du processeur contenu dans la variable pico en simulant l ex cution des instructions Pour cela le simulateur appelle la fonction cycle_d horloge qui ex cute une instruction et fait voluer l tat de la machine en cons quence L ex cution d un programme consiste r p ter cycle_d horloge jusqu ce qu on rencontre une instruction stop La fonction cycle_d horloge devra lire et crire la m moire et les registres Nous d finissons tout d abord une batterie de fonctions auxiliaires qui v rifient que les op rations demand es par le programme sont l gales et acc dent des ressources r elles de la machine Fichier simul ml let lire_registre reg if reg lt 0 reg gt nombre_de_registres then raise Erreur registre ill gal reg pico registres reg let crire_registre reg valeur if reg lt O reg gt nombre_de_registres then Le simulateur 263 raise Erreur registre ill gal reg if reg lt gt 0 then pico registres reg lt valeur let lire_instruction adresse let adr adresse taille _ du mot in if adr lt O adr gt vect_length pico code then raise Erreur sortie de la zone code adr if adresse mod taille_du_mot lt gt 0 then raise Erreur pc non align adresse pico code adr let lire_m moire adresse let adr adresse taille _ du mot in if adr lt O adr gt vect_length pico m moire then raise Erreur lecture e
229. at pas sur le deuxi me cas du filtrage Il faut donc appliquer aux motifs des fonctions d analyse la technique connue sous le nom de factorisation gauche la fonction lLire_expr commence par reconna tre le pr fixe commun aux deux cas c est dire lire_s q puis appelle la fonction d analyse auxiliaire lire_alternative pour tester la pr sence de la barre verticale S il y en a une le premier cas de lire_alternative est s lectionn et appelle r cursivement lire_expr pour lire l expression qui suit Sinon lire_alternative ne lit rien et lire_expr renvoie simplement l expression lue par lire_s q Fichier expr ml let lire function lt function lt 7f gt gt true lt gt gt false chapeau lire_expr r function lt gt gt true lt gt gt false dollar gt gt let ri if dollar then r else S quence r R p tition Caract res tous_car in if chapeau then ri else S quence R p tition Caract res tous_car r1 La fonction lire point d entr e du module lit une expression rationnelle ventuellement pr c d e d un caract re ou suivie d un caract re Remarquez que depuis l int rieur d un motif de flux il est possible d appeler des fonctions d analyse anonymes non nomm es introduites par function 16 3 Les automates Pour programmer la commande grep il faut savoir d terminer si une expression rationnelle reconna t une
230. ateur et les place dans une ou plusieurs fen tres l cran Il associe des fonc tions Caml certains types d v nement tels que un clic de la souris dans un bouton la s lection d une entr e de menu ou l appui d une touche du clavier Finalement il appelle la boucle d interaction de CamITk qui affiche tous les composants l cran g re l interaction avec l utilisateur et appelle les fonctions Caml correspondant aux v nements qui int ressent le programme Commen ons par un exemple tr s simple une interface r duite PES un seul bouton qui affiche le message Bonjour lorsque l utilisateur Ken clique sur le bouton open tk let fen tre principale openTk in let action print_string Bonjour print_newline in let bouton button__create fen tre _principale Text Pressez moi Command action in pack bouton 194 Interfaces graphiques mainLoop Comme tous les programmes CamlTk celui ci commence par un appel openTk Cette fonction initialise la biblioth que CamITk et renvoie un composant qui repr sente la fen tre principale de l application Ensuite le programme cr e le bouton qui constitue l essentiel de son interface l aide de la fonction button__create Comme toutes les fonctions de cr ation de composants CamlTk button__create prend deux arguments un composant p re et une liste d options qui d terminent l apparence et le comporte ment du bo
231. ation classique en informatique Bien que r alis en France Caml est anglophone ses mots cl s sont en anglais Ainsi les valeurs de v rit de la logique math matique le vrai et le faux deviennent true et false en Caml Ce n est pas une r elle difficult car les mots cl s sont peu nombreux et nous les traduirons au fur et mesure Caml apporte une grande aide au programmeur en s effor ant de d tecter le plus possible d erreurs le langage analyse les programmes qui lui sont soumis pour v rifier leur coh rence avant toute tentative de compilation ou d ex cution La principale anal yse de coh rence qu il effectue se nomme le fypage m canisme qui v rifie que les op rations qu on utilise sont d j d finies et que les valeurs qu on leur applique ont un sens Par exemple l addition n est d finie que pour les nombres pas pour les valeurs de v rit ni pour les cha nes de caract res Donc true 1 sera rejet de la m me fa on que 1 oui Vous constaterez vite qu il est ainsi plus difficile d crire en Caml des programmes manifestement faux le langage les rejette automatiquement Le corollaire est videmment qu il est plus facile d crire des programmes corrects Si vous tes familier avec un langage algorithmique classique comme Pascal par exemple vous ne serez pas compl tement d pays par Caml vous y retrouverez la notion de fonction et une notion similaire celle de proc dure d
232. ation du crayon d finies dans le chapitre pr c dent avance tourne vide_ cran et fixe_crayon forment un mini langage graphique compl tement inclus dans Caml En effet il faut n cessairement utiliser les traits syn taxiques de Caml pour d finir les dessins Ainsi la d finition du carr utilise explicite ment les d finitions globales le let la boucle for la s quence et les conventions lexicales de Caml pour les nombres flottants 0 let carr c for i 1 to 4 do avance c tourne 90 0 done Il n y a rien l que de tr s normal apr s tout nous n avons fait qu impl menter un ensemble de fonctions Caml La question est de savoir comment aller plus loin et se d barrasser de la syntaxe de Caml pour notre langage graphique 9 2 Le retard l valuation Voyons o et pourquoi nous nous heurtons des difficult s r elles dans notre qu te de la simplicit Les fonctions avance recule tourne _ _droite et tourne _ _ gauche sont faciles d finir let recule d avance d and tourne_ _droite a tourne a and tourne_ _gauche tourne recule float gt unit lt fun gt tourne_ _droite float gt unit lt fun gt tourne_ _gauche float gt unit lt fun gt Pour lever et baisser le crayon on pourrait crire let baisse_le_crayon fixe_crayon false and l ve_le_ crayon fixe _ crayon true baisse_le_crayon unit gt unit lt fun gt l ve_le
233. atives des op rateurs Nous allons impl menter des conventions de priorit analogues celles de l arithm tique pour les op rations de la logique et est plus prioritaire que ou qui est plus prioritaire que gt etc Dans ce but l analyseur syntaxique est stratifi en fonctions qui analysent des propositions de priorit de plus en plus faible La fonction proposition0 analyse ainsi les propositions les plus simples identificateurs bool ens ou expressions entre parenth ses La fonction propositioni analyse les propositions qui commencent par non ou qui sont des propositions simples Les autres Syntaxe concr te des propositions 219 fonctions proposition2 propositions analysent respectivement les propositions qui comportent un et un ou une implication ou une quivalence Fichier asynt ml open prop open lexuniv let rec lire_proposition f propositions f and proposition0O function lt Ident s gt gt Variable s lt MC vrai gt gt Vrai lt MC faux gt gt Faux lt MC lire_proposition p MC gt gt p and propositioni function lt MC non proposition0 p gt gt Non p lt proposition0 p gt gt p and proposition2 function lt proposition1 p reste2 p q gt gt q and reste2 p function lt MC et proposition1 q reste2 Et p q r gt gt r lt gt gt p and proposition3 function
234. aux deux clauses de la fonction hanoi cas 0 gt et cas n gt Le principe de r currence nous prouve donc que nous savons effectivement r soudre le probl me pour tout n m me si cela ne nous apparaissait pas clairement au d part La difficult intuitive de ce genre de d finitions r cursives est d oser utiliser l hypoth se de r currence il faut supposer qu on sait d j faire pour n 1 disques et crire le programme qui r sout le probl me pour n disques Dans la proc dure hanoi on suppose ainsi deux fois que la fonction saura bien faire toute seule pour n 1 disques et l on ne s occupe que de d placer le gros disque ce qui semble un travail facile Finalement on a l impression de voir tourner du code que l on n a pas crit tellement il semble astucieux l ex cution L criture de fonctions r cursives se r duit ainsi tr s souvent au sch ma Notions de complexit 33 let rec f function O gt solution simple cr D fn D amp eTS On d montre en math matiques qu il n est pas interdit d appeler f sur d autres argu ments que n 1 pourvu qu ils soient plus petits que n par exemple n 2 mais alors il faut pr voir d autres cas simples par exemple 1 gt Un exemple de ce sch ma de programme est la fonction de Fibonacci d finie par let rec fib function 0 gt 1 1 gt 1 n gt fib n 1 fib n 2 fib int gt int lt fun gt fi
235. ayon lectronique et le langage mini Logo et s est poursuivie ensuite sans discontinuer dans des domaines aussi divers que la d monstration de tautologies avec son langage des formules la commande grep avec son langage d expressions rationnelles la pico machine avec son langage d assemblage et bien entendu le mini Pascal et le mini Caml dont les langages associ s taient di rectement des langages de programmation usuels Dans tous les cas nous tions ramen s d finir et impl menter un langage aussi bien en ce qui concerne la syntaxe abstraite et concr te que la s mantique Cette m thodologie est tr s g n rale et f conde Par exemple un grand nombre de com mandes du syst me d exploitation Unix se pr sentent sous la forme de petits langages sp cialis s c est galement le cas d diteurs de textes comme Emacs de traitements de textes comme TFX et m me des langages HTML et XML de description de pages Web C est pourquoi nous avons abondamment illustr cette m thodologie pour vous permettre de la reconna tre dans les probl mes de programmation qui se pr senteront vous 366 En guise de conclusion Les deux modes d valuation Si le volet syntaxique de cette m thode est relativement invariant d une applica tion l autre le volet s mantique se subdivise en deux grandes classes l interpr tation et la compilation Dans les deux cas la s mantique consiste en un calcul de valeurs associ
236. b 10 int 89 Remarquez que cette fonction fait effectivement deux appels r cursifs sur deux valeurs diff rentes mais toutes les deux plus petites que l argument donn Complexit de la proc dure hanoi Il est facile d crire un programme qui compte le nombre de mouvements n cessaires pour r soudre le jeu pour n disques il y a 0 mouvement faire pour 0 disque l appel la proc dure mouvement produit 1 mouvement et le nombre de mouvements n cessaires aux appels r cursifs est forc ment compt par la fonction r cursive de comptage que nous sommes en train de d finir En effet on suppose une fois de plus que pour n 1 la fonction sait faire et on se contente de trouver le r sultat pour n let rec compte_hanoi i d part milieu arriv e function 0 gt 0 n gt compte_hanoi d part arriv e milieu n 1 1 compte_hanoi milieu d part arriv e n 1 compte_hanoi a gt a gt a gt int gt int lt fun gt Les arguments contenant les noms des tiges sont bien s r inutiles et il suffit d crire let rec compte_hanoi_na f function 0 gt 0 n gt compte_hanoi_na f n 1 1 compte_hanoi_na f n 1 compte_hanoi_na f int gt int lt fun gt qu on simplifie encore en let rec compte_hanoi function 0 gt 0 n gt 2 compte_hanoi n 1 1 compte_hanoi int gt int lt fun gt compte_hanoi 3 compte_hanoi 10
237. begin try sp cialisation assoc id env with Not_found gt raise Erreur id est inconnu end Fonction liste_de_cas gt let type_argument nouvelle_inconnue and type_r sultat nouvelle _ inconnue in let type_cas motif expr let type motif env_ tendu type_ motif env motif in unifie type _ motif type_argument let type_expr type_exp env_ tendu expr in unifie type_expr type_r sultat in do_list type_cas liste_de_cas type_fl che type_argument type_r sultat Application fonction argument gt let type_fonction type_exp env fonction in let type_argument type_exp env argument in let type_ r sultat nouvelle _ inconnue in unifie type_ fonction type_fl che type_argument type_r sultat type_r sultat Let d f corps gt type_exp type_d f env d f corps Bool en b gt type_bool Nombre n gt type_int Paire ei e2 gt type_produit type_exp env ei type_exp env e2 Nil gt type_ liste nouvelle _inconnue Cons ei e2 gt let type_e1 type_exp env el in let type_e2 type_exp env e2 in unifie type_liste type_e1 type_e2 type_e2 and type_d f env d f d but_de_d finition let type_expr match d f r cursive with false gt type_exp env d f expr true gt let type_ provisoire nouvelle inconnue in let type_expr type_exp d f nom sch ma _ trivial type_provisoire env d f expr in unifie type_expr type_provisoire type_expr in fin_de_d fi
238. bles partir d un ensemble d tats Elle renvoie un tableau de 256 ensembles d tats qui fait corre spondre chaque caract re l ensemble des tats atteints par transition sur ce caract re Lorsque cet ensemble est vide cela signifie qu il n y a pas de transition possible sur ce caract re Nous pouvons maintenant attaquer la fonction de d terminisation proprement dite L id e de d part est simple pour calculer l tat de l automate d terministe correspon dant un ensemble d tats e on calcule d placements e et pour chaque transition possible on calcule la fermeture de l ensemble d tats destination puis on construit par un appel r cursif l tat destination de la transition qui est l tat correspondant cette fermeture Traduisant directement cette approche en Caml Light on prendrait let rec d terminise ens dterminal exists function e gt e terminal ens l ments dtransitions map_vect d term_ trans d placements ens and d term_trans dest if est_vide dest 318 Recherche de motifs dans un texte then Rejet else Vers d terminise fermeture_ens dest Cette approche est malheureusement inadapt e la structure de graphe des auto mates dans le cas d une transition qui reboucle sur l tat dont elle est issue la fonction d terminise va se rappeler l infini sur le m me ensemble d tats Pour contourner cette difficult il faut s parer construction d un
239. btenir l automate d terministe suivant 2 3 4 5 8 9 2 3 4 5 6 7 10 11 2 3 4 5 8 9 12 Seul l tat 2 3 4 5 8 9 12 est terminal puisque c est le seul contenir l tat terminal 12 de l automate de d part 316 Recherche de motifs dans un texte Nous allons maintenant impl menter cet algorithme de d terminisation en Caml La premi re chose faire est de fournir une repr sentation des ensembles d tats ainsi que les op rations de base sur ces ensembles Fichier determ ml open auto type ensemble_d tats contenu ensent__t l ments auto__ tat list let vide contenu ensent__vide l ments let est_vide ens match ens l ments with gt true let appartient tat ens ensent__appartient tat num ro ens contenu let ajoute tat ens contenu ensent__ajoute tat num ro ens contenu l ments tat ens l ments gt false Un ensemble d tats est repr sent par la liste des tats appartenant l ensemble champ l ments et par un ensemble d entiers champ contenu les num ros des tats appartenant l ensemble On se donne un module ensent qui impl mente le type ensent__t des ensembles d entiers Voici son interface on donne en annexe sec tion 16 7 une impl mentation possible de ce module Fichier ensent mli type t value vide t and appartient int gt t gt bool and ajoute i
240. btiles car lorsqu un bloc m moire est lib r les donn es qu il contenait ne sont pas imm diatement d truites elles resteront valides tant qu on n crira pas d autres donn es au m me en droit Cela signifie que le programme continuera marcher un certain temps apr s la lib ration qui cr e l erreur Au gr du chemin pris dans le programme ces valeurs seront d truites plus ou moins tard donnant l utilisateur l impression que son programme se comporte de mani re erratique 368 En guise de conclusion La r cup ration automatique de m moire La manipulation s re et facile des structures de donn es suppose donc l allocation et la lib ration automatique des blocs de m moire Les programmes Caml s ex cutent donc en collaboration avec un pro gramme sp cialis pour g rer la m moire de la machine le gestionnaire m moire Ce programme se compose de deux parties l allocateur de m moire et le r cup rateur de la m moire inutilis e Le r cup rateur est commun ment appel GC pour garbage col lector litt ralement boueur On traduit g n ralement GC par glaneur de cellules ou encore ramasse miettes Le m canisme g n ral du GC est le suivant lorsque l allocateur de m moire ne peut satisfaire une requ te par manque de m moire libre le GC se d clenche et parcourt r cursivement toutes les donn es utilis es par le pro gramme en cours Il commence par le contenu des re
241. c c synthese mli camlc c synthese ml 360 Un synth tiseur de types camlc c lexuniv mli camlc c lexuniv ml camlc c syntaxe ml camlc c typeur ml camlc o typeur types zo synthese zo lexuniv zo syntaxe zo typeur zo Le programme se lance par camlrun typeur ou typeur__boucle et inf re vaillam ment les types de nos fonctionnelles pr f r es let rec map function f gt function gt a 1 gt fa map f l map pour tout a b Cb gt a gt b list gt a list map function x gt x 1 1 2 8 l int list map function x gt x l a list map function x gt not x 1 2 l Incompatibilit de types entre bool et int let id function x gt x in id id id a gt a 18 9 Pour aller plus loin Complexit de l algorithme de synth se de types Il est tr s difficile de faire l analyse de la complexit de l algorithme de typage que nous avons pr sent C est si vrai qu il a fallu attendre plus de dix ans avant que cette tude soit r alis e par P Kanellakis H Mairson et J Mitchell dans l article Unification and ML type reconstruction Computational Logic Essays in Honor of Alan Robinson MIT Press 1991 Avant cette publication il tait bien connu dans la communaut des chercheurs que la synth se de type d un langage comme Caml tait lin aire Ce r sulta
242. caract re n tait pas dans la cha ne dans ce cas on renvoie false en s quence exception Trouv L exception Trouv est d finie let caract re _dans_ cha ne cha ne car try for i 0 to string_length cha ne 1 do if cha ne i car then raise Trouv done false 130 Le docteur with Trouv gt true caract re_dans_cha ne string gt char gt bool lt fun gt Ici le d clenchement de l exception n est pas un cas d erreur mais plut t un v nement heureux on a d tect la pr sence du caract re dans la cha ne On ne peut pas dire non plus que ce soit vraiment un v nement exceptionnel une exception au calcul normal c est un signal attendu tout simplement Sans le m canisme des exceptions la fonction pr c dente devrait tre crite avec une r f rence initialis e false en d but de boucle et mise true lorsqu on rencontre le caract re let car_dans_ cha ne cha ne car let trouv ref false in for i 0 to string_length cha ne 1 do if cha ne il car then trouv true done ltrouv car_dans_cha ne string gt char gt bool lt fun gt Cette version est un peu moins efficace puisque le parcours de la cha ne est toujours effectu compl tement alors qu il est inutile de le continuer d s qu on a d tect la pr sence du caract re Cet argument d efficacit est minime le choix entre les deux versions est essentiellement
243. cart sien de et B est not x B Cette analogie avec la notation de la multiplication est aussi employ e en Caml d o le symbole dans les types Les valeurs de types produit se notent comme en math matiques on crit les deux l ments du couple entre parenth ses et s par s par une virgule Une petite diff rence d appellation cependant en informatique on parle plus volontiers de paires que de couples De plus en Caml les parenth ses autour des paires ne sont pas toujours strictement n cessaires 1 2 int int 1 2 Les paires sont aussi utilis es en tant qu arguments ou r sultats de fonctions let addition x y x y addition int int gt int lt fun gt addition 1 2 f int 3 l aide de paires on crit des fonctions qui rendent plusieurs r sultats Par exemple la fonction suivante calcule simultan ment le quotient et le reste d une division enti re let quotient _reste x y x y x mod y quotient_reste int int gt int int lt fun gt quotient_ reste 5 3 int int 1 2 Les notations pour les paires se g n ralisent aux triplets aux quadruplets et en fait aux n uplets pour n importe quel nombre d l ments n Par exemple 1 2 3 est un triplet d entiers et poss de le type int int int 64 Fonctionnelles et polymorphisme 4 4 Curryfication proprement parler une fonction prenant une paire comme argu
244. cela donne une autre id e pour crire une version simple et lin aire de la fonction palindrome de la section 2 1 let palindrome s let r rev_string s in F S palindrome string gt bool lt fun gt et m me encore plus bri vement let palindrome s rev_string sS s palindrome string gt bool lt fun gt 3 6 Les r f rences Les r f rences sont des structures de donn es pr d finies qui mod lisent les cases m moire de la machine La propri t caract ristique des cases m moire est qu on peut les lire et les crire la lecture renvoie leur contenu courant l criture change ce contenu Les cases m moire sont utilis es pour repr senter des compteurs ou des accumulateurs dont le contenu volue au cours du calcul Lire et crire les cases m moire Poursuivant l analogie avec les cases m moire vous pouvez vous figurer une r f rence comme une bo te la case m moire qui contient une valeur vous pouvez placer quelque chose dans la bo te criture ou demander ouvrir la bo te pour examiner son contenu lecture Les r f rences sont cr es l aide de la construction ref val o val est la valeur initialement contenue dans la r f rence D finissons par exemple un compteur qui vaut initialement 0 let compteur ref O compteur int ref ref 0 La valeur de compteur est donc une bo te contenant 0 qu on peut repr senter ainsi compteur ol Le contenu cour
245. ch valeuri valeur2 with Variable var ty gt test_d occurrence var ty rectifie_niveaux var niveau ty var valeur lt Connue ty 356 Un synth tiseur de types ty Variable var gt test_d occurrence var ty rectifie_ niveaux var niveau ty var valeur lt Connue ty Terme constri argumentsi Terme constr2 arguments2 gt if constri lt gt constr2 then raise Conflit valeuri valeur2 else for i 0 to vect_length argumentsi 1 do unifie arguments1i i arguments2 i done 18 5 Inconnues g n ralisation et sp cialisation Le module type tient jour le niveau de liaison courant des inconnues Ce niveau est incr ment au d but du typage d une d finition et d cr ment la fin Il mesure la profondeur d imbrication gauche des constructions let Les nouvelles inconnues sont cr es avec le champ niveau gal au niveau courant de liaison Fichier types ml let niveau_de_liaison ref 0 let d but_de_d finition incr niveau_de_liaison and fin_de_d finition decr niveau_de_liaison let nouvelle_ inconnue Variable niveau niveau_de_liaison valeur Inconnue L op ration de g n ralisation consiste trouver dans le type g n raliser toutes les variables dont le niveau est strictement plus grand que le niveau courant de liai son En supposant qu on appelle g n ralisation juste apr s fin_de_ d finition ces variables sont exactement
246. chat Essayez de ne plus y penser gt gt C est pas facile ils pleurent tout le temps Que pensez vous de la vie en g n ral gt gt Vaste question Que pensez vous de Caml gt gt Voil qui est franchement pr cis C est un superbe langage de programmation Je ne connais que le langage Caml gt gt a m tonne que vous conna issiez un langage de programmation Parlons de vous c est plus important gt gt Oui J aime ma femme mes enfants les fins de semaine la mer Est ce une femme ordinaire 144 Le docteur gt gt Non si vous saviez combien elle est extraordinaire Moi je ne suis qu une machine gt gt Bien sympathique au demeurant Que pensez vous de Linux gt gt N auriez vous pas un l ger tropisme vers l informatique Excusez moi gt gt Vous tes toute excus e Ne m en veuillez pas si je vous interroge Continuez gt gt Mon chat angora est mort vous disais je Je vous plains beaucoup gt gt Oui mais cela ne me console pas vraiment Que faut il faire Permettez moi de ne pas r pondre gt gt Mais qui pourra m aider alors Pourquoi me posez vous cette question gt gt Parce que j ai besoin d aide videmment Parlez moi encore de vous gt gt J ai besoin d aide Que pensez vous des ordinateurs gt gt Ce sont des machines compl tement idiotes Connaissez vous bien l informatique gt gt Un peu Je suis informaticien professionnel Quel beau
247. cl_proc list foncs string d cl_fonc list let environnement_initial p f vars procs p foncs f let ajoute_variable nom info env vars nom info env vars procs env procs foncs env foncs let cherche nom liste try assoc nom liste with Not_found gt raise Pas_trouv nom let cherche_variable nom env cherche nom env vars and cherche_fonction nom env cherche nom env foncs and cherche_proc dure nom env cherche nom env procs Typage des expressions L impl mentation du module typage commence par trois fonctions l mentaires de v rification sur les types Fichier typage ml open syntaxe open envir let v rifie_type message type_attendu type_r el if type_attendu lt gt type_r el then raise Erreur_typage Conflit message type_attendu type_r el let v rifie_tableau function Array inf sup l ments gt l ments _ gt raise Erreur_typage Tableau_attendu let v rifie_non_tableau message function Array inf sup l ments gt raise Erreur_typage Tableau_interdit message lez gt OMS Passons ensuite la fonction type_expr qui calcule le type d une expression ou d clenche l exception Erreur_typage si l expression est mal typ e Cette fonction prend en argument un environnement qui fait correspondre aux variables leur type aux proc dures et aux fonctions leur d claration Fichier typage ml let rec
248. compile_expr env arg2 reg_libre 1 reg_libre reg_libre 1 end else begin r serve_pile 1 printf store sp 0 r d n reg_libre compile_expr env arg2 reg_libre printf load sp 0 r 29 n 298 Compilation de mini Pascal lib re_pile 1 29 reg_libre end end La fonction compile_arguments impl mente la strat gie d valuation pr sent e plus haut Elle value deux expressions en s quence et renvoie les num ros de deux registres contenant leur valeur Le dernier argument reg_libre est le num ro du premier reg istre libre Tous les registres inf rieurs reg_libre seront pr serv s tous les autres peuvent tre utilis s librement Si on peut permuter sans risques les deux valuations et si cela peut r duire le nombre de registres utilis s c est dire si arg2 a de plus grands besoins que arg1 la fonction compile_arguments se rappelle apr s avoir permut arg2 et argi Sinon elle commence par mettre le code valuant arg1 dans reg_libre Ensuite reg_libre n est plus libre il contient la valeur de arg1 Donc de deux choses l une ou bien on peut valuer arg2 avec les registres restants auquel cas la fonction met le code qui value arg2 avec reg_libre 1 comme registre de destination ou bien on n a plus assez de registres libres auquel cas la fonction sauvegarde la valeur de arg1 sur la pile ce qui lib re le registre reg_libre met le code qui value arg2 dans reg_libre et rech
249. conditions peut tre lev e si vous obtenez l autorisation du titu laire des droits sur cette oeuvre e Rien dans ce contrat ne diminue ou ne restreint le droit moral de l auteur ou des auteurs mes parents Suzanne et Michel Lise Marie Jean Baptiste et Ir ne H l ne Pierre Weis Table des mati res Avant propos I Programmer en Caml Avertissement 1 Premiers pas 1 1 Id es g n rales sur Caml 1 2 Dialoguer avec Caml 1 3 Les d finitions 1 4 Fonctions 1 5 Valeurs et programmes 1 6 Impression 1 7 Conventions syntaxiques 1 8 Diagrammes syntaxiques R cursivit 2 1 Fonctions r cursives simples 2 2 D finitions par cas le filtrage 2 3 Les tours de Hanoi 2 4 Notions de complexit Programmation imp rative 3 1 La programmation imp rative 3 2 Boucles 3 3 Manipulation de polyn mes 3 4 Impression des polyn mes 3 5 Caract res et cha nes de caract res 3 6 Les r f rences 3 7 Un programme utilisant des r f rences 3 8 R cursivit et boucles 3 9 R gle d extensionnalit 3 10 Effets et valuation Fonctionnelles et polymorphisme 4 1 Notion de polymorphisme 4 2 Fonctions d ordre sup rieur 43 Typage et polymorphisme 4 4 Curryfication D OO CO e 13 15 17 19 19 27 28 31 37 37 39 40 42 46 47 49 50 52 53 57 57 59 61 64 viii Table des mati res 4 5 Une fonctionnelle de tri polymorphe 65 4 6 La pleine fonctionnalit 67 4 7 Comp
250. core 3 pour valuer 1 2 3 D autre part une phrase peut s tendre sur autant de lignes que n cessaire la fin de la ligne ne se confond donc pas avec la fin de la phrase On devra donc crire pour signaler la fin de la phrase Il faut bien entendu galement appuyer sur la touche retour chariot return en anglais comme c est traditionnel pour toute interaction avec un ordinateur En r ponse au signe d invite de Caml le caract re que Caml imprime pour indi quer qu il attend que nous tapions quelque chose demandons lui d effectuer un petit calcul l addition de 2 et de 2 Pour cela nous entrons simplement l op ration effectuer 2 2 suivie de la marque de fin de phrase 2 2 int 4 Caml nous r pond imm diatement en indiquant par un signe que nous avons simple ment calcul une valeur que cette valeur est de type entier int et qu elle vaut 4 4 Vous constatez que Caml a d duit tout seul le type du r sultat du calcul Pour un exemple si simple ce n est pas vraiment impressionnant mais c est un m canisme ab solument g n ral quelle que soit la complexit du programme que vous lui soumettrez Caml en d duira le type sans aucune intervention de votre part 1 3 Les d finitions Vous pouvez donner un nom une valeur que vous calculez pour ne pas perdre le r sultat de votre calcul La construction qui permet ainsi de nommer des valeurs s appelle une d finition
251. correct d op rer sur une variable dont la valeur est connue il faut directement op rer sur la valeur de cette variable Bien s r si la valeur est elle m me une variable connue il faut aller chercher la valeur suivante C est la t che de la fonction valeur_de sauter par dessus les variables connues jusqu obtenir soit un terme soit une variable inconnue L unification 393 Fichier types ml let rec valeur_de function Variable valeur Connue tyi as var gt let valeur_de_tyi valeur_de tyi in var valeur lt Connue valeur_de_tyl valeur_de_tyl ty gt ty La fonction valeur_de profite de sa recherche de la valeur d une inconnue pour rac courcir le chemin qui m ne cette valeur Le lecteur cultiv aura reconnu la structure de donn es union find et op ration de path compression En reprenant l exemple des trois variables de types t1 t2 et t3 voici graphiquement l effet physique d un appel de valeur_de sur la variable t Effets de l application de valeur_de t i valeur_de t renvoie int et modifie t et to il l E ail l E int int int int int int Pr vention des cycles Un autre cueil concerne l quation toute simple t t Pour la prendre en compte il suffit bien entendu de ne rien faire Cependant il faut pr voir explicitement ce cas dans les programmes sous peine de faire pointer la variable de type t vers elle m me et qui plus est d
252. crayon La seule subtilit pour l ordre Rep consiste it rer l valuation sur la liste des ordres l aide de la fonctionnelle do_list let rec ex cute_ordre function Av n gt avance flottant n Re n gt avance flottant n Tg a gt tourne flottant a Td a gt tourne flottant a Le gt fixe _ crayon true Bc gt fixe _ crayon false Ve gt vide_ cran Rep n 1 gt for i 1 to n do do_list ex cute_ordre 1 done ex cute_ordre ordre gt unit lt fun gt Si nous consid rons qu un programme du langage graphique n est rien d autre qu une liste d ordres alors la fonction qui ex cute les programmes n est qu une banale it ration de la fonction ex cute_ordre sur tous les ordres qui composent le programme let ex cute_programme 1 do_list ex cute_ordre 1l ex cute_programme ordre list gt unit lt fun gt Nous pouvons maintenant crire let carr c Rep 4 Av c Td Entier 90 carr nombre gt ordre lt fun gt ex cute_programme Ve carr Entier 100 carr Entier 75 carr Entier 50 carr Entier 25 carr Flottant 12 5 carr Flottant 6 25 carr Flottant 3 125 unit Syntaxe et s mantique 159 9 4 Syntaxe et s mantique Nous avons pu impl menter r p te et tous les nouveaux ordres graphiques ainsi que des nombres comportant la fois des entiers et des flottants
253. ct res et cha nes de caract res En Caml les cha nes de caract res sont consid r es comme des structures de donn es physiquement modifiables les cha nes se comportent essentiellement comme des tableaux de caract res On b n ficie ainsi d un acc s direct aux caract res et de la possibilit de modifier en place les caract res La syntaxe de l affectation et de l acc s aux caract res des cha nes est similaire celle des tableaux avec des crochets la place des parenth ses Acc s dans une cha ne s s indice Modification d un caract re d une cha ne s s indice lt expression Comme pour les tableaux on parcourt donc compl tement une cha ne de caract res par une boucle for commen ant en 0 et finissant la longueur de la cha ne moins 1 c est dire string_length 5 1 Par exemple on calcule l image miroir d une cha ne en cr ant une cha ne de m me longueur dont on crit tous les caract res l aide d une boucle for Les r f rences 47 let rev_string s let 1 string_length s in let res make_string 1 in for i 0 to 1 1 do res i lt s 1 1 i done res rev_string string gt string lt fun gt La primitive make_string permet de cr er une cha ne de caract res d une longueur donn e et initialis e avec un caract re donn c est donc l analogue de make_vect pour les cha nes de caract res Au passage
254. ction lire_phrase ici la repoussant sans vergogne la fin de ce chapitre pour passer plus vite aux choses s rieuses 17 2 L valuateur Repr sentation des valeurs Notre valuateur manipule des donn es tr s simples du type valeur Ce sont les valeurs utilis es par le langage aussi bien que les r sultats des valuations Les valeurs L valuateur 327 sont de cinq esp ces possibles des nombres entiers des bool ens des fonctions des paires ou des cellules de listes Les fonctions se divisent en deux classes les op rations primitives qui op rent directement sur le type valeur et les fonctions de l utilisateur Les fonctions de l utilisateur sont repr sent es par des fermetures Une fermeture est une paire dont la premi re composante est la d finition de la fonction c est dire le filtrage qui calcule le r sultat de la fonction partir de son argument et la seconde composante est l environnement qui pr valait quand on a d finit la fonction Nous allons voir pourquoi ce codage complexe des valeurs fonctionnelles est ad quat la d finition et l ex cution des fonctions Caml Fichier eval mli open syntaxe type valeur Val_nombre of int Val_bool enne of bool Val_paire of valeur valeur Val_nil Val_cons of valeur valeur Val_fermeture of fermeture Val_primitive of valeur gt valeur and fermeture d finition motif expression list mutable enviro
255. ction ajoute qui est quivalente l op rateur infixe En effet en Caml on fait r f rence la forme pr fixe d un op rateur infixe comme en le faisant simplement pr c der du mot cl prefix prefix int gt int gt int lt fun gt prefix 1 2 int 3 Cette facilit conduit des d finitions de somme et produit en une ligne apr s une tape de 7 contraction let somme it_ list prefix O and produit it_list prefix 1 somme int list gt int lt fun gt produit int list gt int lt fun gt Graphiquement cela s exprime par les deux r critures suivantes somme l gt it_list prefix Ol ie FRS PR e i en FUN PR e2 Do ce Cn 1 X ra is 2N FN En 0 roduit l E it_list prefix 11 i PE FN j En 2N DR 2 En 1 X LA Fu PEU 96 Listes Est ce plus clair que notre premi re version de somme d finie par filtrage sur les listes Pas pour les auteurs de ce livre en tout cas nous pensons que cette criture semblera souvent obscure d autres programmeurs y compris vous m me trois mois apr s avoir crit ce code Si vous voulez tre lisible vitez ce style de programmation sans vari ables particuli rement si vous tes capable d crire du code qui utilise encore plus de fonctionnelles que celui de somme ce code peut devenir trop l gant pour tre maintenu Accumuler encore tant
256. ction blit_string pour les cha nes Il s agit l d une extension de la taille de la m moire virtuelle de l assembleur lorsque le code est compl tement assembl l assembleur pourra d terminer exactement la taille du programme qui sera celle qu on attribuera l ex cution En effet dans le pico processeur comme dans le monde r el la m moire programme est fix e une fois pour toutes au lancement Il n est pas possible de changer la taille de la zone programme pendant que la pico machine est en marche D ailleurs pourquoi en aurait on besoin puisqu il s agit alors d ex cuter un certain programme fix Nous d taillons maintenant le code de la fonction qui r sout les tiquettes en mod ifiant les instructions o elles sont apparues alors qu on ne connaissait pas encore leur valeur Les tiquettes qui rep rent une instruction dans la m moire programme peu vent appara tre dans les instructions de branchement donc comme argument des in structions Jmp Braz ou Branz Ce sont les trois derniers cas du filtrage qui d finit la variable nouvelle_instruction qui a videmment pour valeur l instruction provi soirement crite par l assembleur mais avec la valeur maintenant connue de l tiquette Les tiquettes peuvent aussi appara tre dans des op rations comme deuxi me argu ment constant en effet il est parfois n cessaire de lire ou d crire en m moire des donn es l adresse d une instruction par
257. cursives Caml est sugg r par le pseudo programme suivant let rec f function cas simple gt solution simple autre cas simple gt autre solution simple cas g n ral gt f cas plus simple Il est donc tr s fr quent que le filtrage dirige l criture des fonctions Par exemple si l on d finit une fonction sur les listes on crira presque sans r fl chir let rec f function Cl gt x 1 gt titre d entra nement avant d attaquer les fonctionnelles d usage g n ral sur les listes nous allons mettre en pratique cette programmation assist e par filtrage dans un cas simple le tri des listes 5 3 Tri par insertion Nous impl mentons le tri par insertion qui est un algorithme naturellement r cursif On suppose qu une sous partie du tableau trier est d j tri e et on y ins re la bonne place le prochain l ment de la partie non tri e du tableau Nous en donnons une version fonctionnelle sur les listes Tri par insertion 79 Tri sur listes L id e est qu il est facile de ranger un l ment sa place dans une liste d l ments d j tri e Nous supposons donc avoir d j crit une fonction ins re qui ins re un l ment la bonne place dans une liste tri e Nous crivons maintenant la fonction de tri Cette fonction travaille sur des listes elle doit donc envisager les deux cas possibles de listes let tri_par_insertion f
258. d une boucle de 0 9 Nous d finissons une proc dure imprime_chiffre dont l argument est rien et nous la d clenchons en l appliquant rien let imprime chiffres for i 0 to 9 do print_int i done print _newline imprime_chiffres unit gt unit lt fun gt imprime chiffres 0123456789 unit 40 Programmation imp rative 3 3 Manipulation de polyn mes Nous continuons l apprentissage de la programmation imp rative par l tude des tableaux titre d illustration nous crivons un jeu de fonctions qui impl mentent les op rations de base sur les polyn mes Avant de nous lancer dans la programmation nous rappelons bri vement ce que sont les polyn mes Les polyn mes une ind termin e Des classes l mentaires on retient souvent qu un polyn me est une somme de puissances de x Par exemple p x 2x 3 est un polyn me La variable x est appel e l ind termin e du polyn me Un polyn me est une somme de termes l mentaires qu on nomme mon mes par exemple x et 2x tant donn e une variable x on appelle mon me de coefficient a et de degr i l expression a xt Le degr d un polyn me est celui de son mon me de plus haut degr On rappelle que x x et x 1 Le mon me de degr 0 est donc r duit une constante c est 3 pour p et celui de degr 1 au produit d un nombre par l ind termin e c est 2x pour p D autre part nous util
259. d finies ref string proc dure list proc dures_d finies string proc dure list ref ref let d finit proc dure nom proc as liaison proc dures_d finies liaison proc dures_d finies and d finition de nom_de_proc dure assoc nom_de_proc dure lproc dures_d finies d finit_proc dure string proc dure gt unit lt fun gt d finition_de string gt proc dure lt fun gt L ex cution des ordres Comme la fonction d valuation des expressions la fonction d ex cution des ordres doit g rer un environnement puisqu elle est charg e de lier les arguments des proc dures lorsqu on les appelle L ex cution des ordres simples ne change pas on applique tou jours les fonctions de base du crayon La seule diff rence consiste valuer l expression argument de l ordre en appelant valeur_expr dans l environnement courant Par exem ple pour Av e on appellera comme auparavant la fonction avance avec pour argument le flottant obtenu par l valuation de e c est dire valeur_expr env e L ordre r p te prend maintenant une expression en argument cette expression est valu e et retourne une valeur de type nombre Cependant ce nombre n est pas forc ment un entier dans le cas o c est une valeur flottante deux options sont possibles prendre la d cision d arrondir le nombre l entier le plus proche r p ter 3 1 fois signifie alors r p ter 3 fois ou bien
260. de l crire simplement ce qui sous entend qu elle est vraie On crira par exemple Si un triangle a trois angles de 60 degr s alors ses trois c t s ont m me longueur et non pas L implication si un triangle alors est vraie En revanche on pr cise explicitement qu une proposition est fausse Le but du d monstrateur est donc de montrer qu une proposition est toujours vraie Pour cela il d montre que pour toutes les valeurs possibles des propositions l mentaires la proposition d montrer a toujours la valeur de v rit vrai Con ceptuellement cela correspond tablir la table de v rit de la proposition et v rifier que la colonne de droite celle de la proposition d montrer ne contient que des valeurs v En logique une proposition toujours vraie est aussi appel e une tautologie Nous dirons donc que notre programme est un d monstrateur de tautologies Nous lui ajou tons un raffinement suppl mentaire au cas o la proposition qui lui est soumise n est pas une tautologie le programme renvoie une r futation c est dire un choix de valeurs de v rit pour les propositions l mentaires qui rend fausse la proposition soumise L architecture du programme suit exactement la m thode des tables de v rit pour calculer les valeurs de v rit des lignes de la table nous allons crire un sous programme qui calcule la valeur de v rit d une proposition en fonction de ses
261. de mini Pascal Bloc liste_instr gt do_list compile_instr env liste_instr and affecte_var env nom reg let var cherche _variable nom env in match var emplacement with Global_indirect n gt printf store r 0 d r 44 s n n reg nom Local_indirect n gt printf store sp d r 44 s n Iprofondeur_pile n reg nom Pour l instruction if e then 1 else le code produit a la forme suivante code pour valuer e dans le registre r 1 braz r 1 Ln branche si r 1 est false code pour ex cuter i1 braz r 0 Lm branche toujours Ln code pour ex cuter iz Lm suite du programme Les tiquettes Ln et Lm sont de nouvelles tiquettes produites par la fonction nouvelle_ tiq Dans le cas o 42 est l instruction vide cas d un if sans partie else on supprime le branchement Lm qui ne sert rien dans ce cas On proc de de m me pour l instruction while e do Le test est plac la fin du corps de la boucle pour ne faire qu un saut par tour de boucle au lieu de deux braz r 0 Lm branche toujours Ln code pour ex cuter Lm code pour valuer e dans le registre r 1 branz r 1 Ln branche sir 1 est true suite du programme Compilation des fonctions et des proc dures La compilation d une fonction ou d une proc dure se fait en deux parties il faut d une part attribuer des emplacements aux param tres et aux variables locales et construire l environnement correspondant d
262. dernier exemple utilise la fonction pr d finie qui concat ne deux listes let rec somme function let rec produit function 0D gt 0 D gt 1 x 1 gt x somme l x 1 gt x produit l somme int list gt int lt fun gt produit int list gt int lt fun gt let rec implose function gt mn x 1 gt x implose l implose string list gt string lt fun gt implose Bonjour tout le monde string Bonjourtoutle monde let rec concat ne_listes function 0D gt O x l1 gt x concat ne_listes l concat ne_listes a list list gt a list lt fun gt concat ne_ listes 1 2 3 4 5 6 int list 1 2 3 4 5 6 On constate que toutes ces fonctions utilisent le m me sch ma r cursif en cas de liste vide on rend un certain l ment de base en cas de liste non vide on appelle une fonction deux arguments avec pour premier argument la t te de la liste et pour second argument un appel r cursif sur la fin de la liste Pour somme l l ment de base est O et l op ration est pour produit c est 1 et pour implose c est et enfin pour concat ne_listes c est et Pour obtenir notre fonctionnelle g n rale qui impl mente ce sch ma de programme il nous suffit donc d abstraire la fonction et l l ment de base Une petite remarque syntaxique au pr alable toutes les
263. dernier probl me r soudre est celui du stockage du codage utilis la compression en t te du fichier compress Pour rester simple nous stockons ce codage sous la forme de son arbre de Huffman en utilisant les fonc tions d entr e sortie structur e output_value et input_value La fonction pr d finie output_value de type out_channel gt a gt unit crit une repr sentation de son argument sous forme d une suite d octets sur le canal sp cifi L argument est une struc ture Caml quelconque ou presque elle ne doit pas contenir de valeurs fonctionnelles La fonction input_value effectue l op ration inverse elle lit une suite d octets sur un canal et renvoie la structure Caml correspondante Ces deux fonctions sont tr s rapi des et vitent d avoir crire soi m me des fonctions de conversion entre structures de donn es et suites d octets Le format de donn es utilis pour stocker l objet dans le fichier n est pas du texte directement lisible par l utilisateur mais un codage binaire de l objet Il est destin tre relu par des machines non par des humains Un fichier compress se compose donc d un arbre de Huffman crit par output_value suivi par les donn es compress es crites par encode Fichier huffman ml let compresse entr e sortie let fr q fr quences entr e in let arbre construire_arbre fr q in let codage arbre_vers_codage arbre in output_value sortie a
264. des calculs sur les polyn mes d abord repr sent s par des tableaux dans le chapitre 3 section 3 3 puis comme des listes dans le chapitre 5 section 5 5 Nous avons appel les seconds polyn mes creux les premiers polyn mes pleins Maintenant se pose videmment le probl me de travailler avec ces deux repr sentations en m me temps pour b n ficier des avantages de chacune d elles lorsqu un polyn me est plein la repr sentation l aide d un tableau est conomique car les degr s sont implicites en revanche lorsqu un polyn me est creux comporte beaucoup de coefficients nuls la repr sentation en liste est pr f rable quand elle n est pas tout simplement la seule envisageable comme pour le polyn me 1 1000000 Nous aimerions donc repr senter les polyn mes par un tableau ou une liste selon le cas mais d finir des op rations qui travaillent indiff remment sur l une ou l autre des repr sentations Or ces deux types de repr sentations sont incompatibles au point de vue du typage Consid rons la proc dure d impression des polyn mes nous avons d fini deux fonctions sp cifiques chacune des repr sentations imprime_polyn me_plein int vect gt unit qui imprime les polyn mes pleins et imprime_polyn me_ creux int int list gt unit qui imprime les polyn mes creux Pour avoir une primitive d impression travaillant sur tous les polyn mes on aurait donc envie d crire let imprime_
265. donn en argument n est pas un programme complet mais seulement un morceau de programme L ex cution de la commande camlc c crayon ml produit deux fichiers e le fichier crayon zo qu on appelle fichier de code objet il contient du code compil pas encore ex cutable car faisant r f rence des identificateurs ext rieurs e le fichier crayon zi qu on appelle fichier d interface compil e il contient des informations de typage sur les objets d clar s dans le module crayon types des identificateurs d finis noms des types concrets d clar s avec leurs constructeurs etc Le fichier d interface compil e crayon zi sert pour la compilation des modules qui utilisent le module crayon quand on compile un module contenant open crayon ou un nom qualifi de la forme crayon__ le compilateur lit le fichier crayon zi et y trouve toutes les informations de typage dont il a besoin Ce comportement introduit une contrainte sur l ordre dans lequel on compile les modules lorsqu on compile un module il faut avoir compil au pr alable tous les mod ules qu il utilise ayant ainsi produit tous les fichiers zi n cessaires sa compilation Dans le cas du mini Logo ces contraintes se r sument par le sch ma suivant une fl che de vers B signifie que utilise B et donc que B doit tre compil avant Interfaces de modules 187 logo ml langage ml asynt ml alex ml cra yon ml La s que
266. donn e ladresse_donn e taille_du_type typ ajoute_variable nom typ typ emplacement emplacement env let compile_programme prog adresse_donn e 0 let env_global list_it alloue_variable_globale prog prog_variables environnement_initial prog prog_proc dures prog prog_fonctions in compile_instr env_global prog prog_corps printf stop n do_list compile_proc dure env_global prog prog_proc dures do_list compile_fonction env_global prog prog_fonctions Le compilateur complet Pour terminer voici le programme principal qui combine l analyseur syntaxique le v rificateur de types et le compilateur Fichier cpascal ml open syntaxe let compile_fichier nom try let canal open_in sys__command_line 1 in try let prog lire_programme stream_of_channel canal in close_in canal typage__type_programme prog compil__compile_programme prog with Parse_error Parse_failure gt prerr_string Erreur de syntaxe aux alentours du caract re num ro prerr_int pos_in canal prerr_endline typage__Erreur_typage err gt typage__affiche_erreur err Compilation with sys__Sys_error message gt prerr_string Erreur du syst me if sys__interactive then else begin compile_fichier sys__command_line 1 exit O end 303 prerr_endline message Mise en pratique Pour compiler le tout camlc c lexuniv mli camlc c lexuniv ml camlc c syntaxe mli camlc c
267. droite du disque La fonction suivante construit un disque pos sur une tige c est dire entour d un certain nombre d espaces de fa on ce que le disque occupe la m me largeur que la tige sur laquelle il est pos let disque_num ro n taille_grand_disque let partie_blanche blancs taille_grand_disque 1 n in partie_blanche disque n partie _ blanche disque_num ro int gt int gt string lt fun gt La derni re fonction dessine la base d une tige sous la forme let base_de_tige taille_grand_disque let moiti make_string taille_grand_disque mon in moiti moiti base_de_tige int gt string lt fun gt Un disque est repr sent par un simple num ro sa largeur Une tige est repr sent e par un couple entier liste d entiers La premi re composante est le nombre de cases libres en haut de la tige la seconde la liste des disques pos s sur la tige La fonction tige suivante construit la liste des cha nes de caract res repr sentant les disques pos s sur une tige let rec tige taille_grand_disque function I D gt 0 0 t te reste gt disque_num ro t te taille_grand_disque Animation des tours de Hanoi 89 tige taille_grand_disque 0 reste d calage liste gt disque_num ro 0 taille_grand_disque tige taille_grand_disque d calage 1 se tige int gt int int list gt string list lt fun gt Par
268. e menu string vect gt unit gt a vect gt a lt fun gt La fonction pr d finie string_of_int renvoie la cha ne de caract res correspondant son argument entier titre d monstratif nous appelons la proc dure avec une troisi me option qui con siste ne rien faire la proc dure associ e est simplement la fonction identit sp cialis e au type unit que nous fournissons comme une fonction anonyme menu Arr ter Continuer Ne rien faire au_revoir continuer function gt l lt 0 gt Arr ter lt 1 gt Continuer lt 2 gt Ne rien faire Choisissez votre option 2 unit Utiliser les types pour viter les erreurs Fournir deux tableaux distincts pour les options et les messages d invite est source d erreurs puisque le typage n assure pas la correspondance entre l invite et l option La correction est ais e il suffit de n utiliser qu un seul tableau contenant des paires dont La pleine fonctionnalit 69 le premier l ment est un message d invite et le second l option associ e Cet exemple nous am ne d finir les fonctions d acc s aux composantes d une paire traditionnelle ment nomm es fst pour first qui signifie premier en anglais et snd pour second second Bien que ces fonctions soient pr d finies en Caml nous crivons leur code car il est l gant On op re tout simplement par filtrage de la paire argument
269. e cette repr sentation des types et des variables de type Nous repr sentons les variables de type par des bo tes qui pointent vers une valeur soit la valeur Inconnue si la variable reste une inconnue soit le type correspondant Par exemple dans le sch ma suivant t est une inconnue tandis que t2 vaut int Inconnue int Nous repr sentons les types construits soit simplement par leur nom quand ils ne poss dent pas d arguments soit par une bo te comportant des pointeurs vers les argu ments du type Voici les repr sentations du type int int et du type t int quand t est une inconnue PEN i Ih int int int Inconnue Modification physique directe des variables de type tudions le d roulement de la r solution du syst me d quations ty int to tj int Au d part nous introduisons les deux inconnues t et to Inconnue Inconnue La prise en compte de t int s effectue par simple modification physique du champ valeur de l inconnue t pour le faire pointer vers le type int t devient int La Inconnue Inconnue int Inconnue 350 Un synth tiseur de types Le traitement de l quation t2 t int est similaire t devient t int 8 int Inconnue int gt L h int int Comme nous l avons dit les types sont partag s ce qui implique que la modification d un type entra ne automatiquement la modification de tous les types dans lesquels il intervient N
270. e Par exemple la syntaxe concr te avance 30 a pour syntaxe abstraite Av Entier 30 La syntaxe abstraite de notre langage graphique est donc d crite par le type Caml ordre Intuitivement la syntaxe abstraite donne la signification de la phrase analys e d une mani re synth tique et ind pendante des vari ations possibles de la syntaxe concr te Par exemple nous tol rerons les abr viations d ordres graphiques comme av au lieu de avance L expressions av 30 aura donc la m me syntaxe abstraite que avance 30 soit Av Entier 30 Ainsi nos fonctions d ex cution des ordres graphiques n auront m me pas savoir qu il existe deux moyens de dire avance puisque leur argument sera exactement le m me dans les deux cas C est un exemple tr s simple de normalisation des donn es avant traitement Nous r sumons syntaxe concr te syntaxe abstraite et s mantique des ordres graphiques dans le tableau suivant 160 Syntaxe abstraite syntaxe concr te Syntaxe concr te Syntaxe abstraite S mantique signification Langage graphique Langage Caml Dessin l cran ou modifi Monde du crayon Monde Caml cation de l tat du crayon avance 30 0 Av Flottant 30 0 avance 30 0 av 30 0 Av Flottant 30 0 avance 30 0 recule 10 0 Re Flottant 10 0 avance 10 0 re 10 Re Entier 10 avance 10 0 gauche 10 Tg Entier 10 tourne 10 0 tg 10 Tg Entier 10 tourne 10 0 droite 10 Td Entier 10 tourne 10
271. e Pour que l extraction et l ajout soient efficaces il faut que l arbre ait les branches les plus courtes possible c est dire qu il soit aussi bien quilibr que 250 Compression de fichiers possible Une mani re d obtenir ce r sultat est d ins rer toujours du m me c t disons droite mais de permuter les fils gauche et droit chaque descente r cursive Cela suffit garantir que l arbre est toujours quilibr m me apr s une longue s quence d ajouts Fichier fileprio ml let rec ajoute file prio elt match file with Vide gt File prio elt Vide Vide File prioi elti gauche droite gt if prio lt priol then File prio elt ajoute droite prioi elti gauche else File priol elti ajoute droite prio elt gauche Pour ce qui est de l efficacit de cette impl mentation on constate qu un appel de ajoute ou de extraire parcourt au plus une branche enti re de l arbre Comme l arbre est quilibr la longueur d une branche est de l ordre de log n o n est le nombre d l ments dans l arbre L ajout et l extraction se font donc en temps logarithmique en le nombre d l ments de la file d attente ce qui donne une bien meilleure efficacit que l impl mentation base de listes En particulier la construction de l arbre de Huffman n cessite moins de 2000 tours dans la fonction ajoute soit huit fois moins qu avec l impl mentation na ve Entr e
272. e list prog_proc dures string d cl_proc list prog_fonctions string d cl_fonc list prog_corps instruction value lire_programme char stream gt programme L impl mentation du module syntaxe est enti rement consacr e l analyseur syntax ique la fonction lire_programme d clar e ci dessus Nous r utilisons l analyseur lex ical universel lexuniv introduit au chapitre 12 pour la lecture des propositions et utilis galement au chapitre 14 pour l assembleur de la pico machine Fichier syntaxe ml open lexuniv let analyseur_lexical construire_analyseur false true not a Me GUESS SN s MLE MS and More tif MEthen s else while do write read begin end integer boolean array of var procedure function program L analyseur lexical s obtient par application partielle de la fonction construire_ analyseur la liste des mots cl s Viennent ensuite deux puissantes fonctionnelles d analyse syntaxique lune pour analyser des listes l autre pour analyser des applica tions d op rateurs infixes Voici la fonctionnelle d analyse des listes Fichier syntaxe ml let lire_liste lire_ l ment s parateur let rec lire_reste function lt stream_check function lex me gt lex me MC s parateur s p lire_ l ment elt 280 Compilation de mini
273. e Data compression methods and theory de James Storer Computer Sci ence Press et Text compression de Bell Witten et Cleart Prentice Hall Pour ce qui est des algorithmes sur les files d attente on se reportera l un des classiques de l algorithmique comme par exemple le volume 3 de The art of computer programming de Donald Knuth Addison Wesley 14 Simulation d un processeur O l on apprend g rer les RISC EAUCOUP DE PROGRAMMES D ORDINATEUR servent simuler des processus physiques l ordinateur offrant sa puissance de calcul pour faire voluer les nombreux param tres du syst me Nous crivons maintenant un programme de ce type il simule le fonctionnement d un processeur ou unit centrale d ordinateur Le simulateur lit des programmes crits dans le langage d assemblage de notre pro cesseur imaginaire et les ex cute comme le ferait un processeur r el Pour l instant nous crirons les programmes assembleur la main dans le chapitre 15 nous ver rons comment produire automatiquement ces programmes par traduction partir d un langage de haut niveau Ce chapitre constitue une introduction au mod le de processeurs RISC reduced instruction set computer processeur jeu d instruction r duit Le lecteur est sup pos conna tre dans ses grandes lignes le fonctionnement d un processeur et avoir d j programm ne serait ce qu une fois dans un langage d assemblage 14 1 Le pico process
274. e beaucoup la limite sup rieure des entiers repr sentables en Caml Nous reviendrons plus tard sur les nombres en virgule flottante aussi appel s nombres flottants chapitre 8 Pour l instant il suffit de savoir qu un nombre flottant est caract ris par le point qui pr c de sa partie d cimale et que les op rations associ es aux flottants sont suffix es galement par un point etc Nous impl mentons donc notre fonction en utilisant la fonction puissance des nombres flottants power let compte_hanoi_rapide n power 2 0 n 1 0 compte_hanoi_rapide float gt float lt fun gt compte_hanoi_rapide 64 0 float 1 84467440737e 19 Un algorithme correct mais inutilisable Gr ce notre d monstration math matique nous avons tabli une formule de cal cul direct du nombre de mouvements n cessaires la r solution du jeu pour n disques Nous avons ainsi tr s fortement acc l r la fonction compte_hanoi C tait indispens able car notre premi re version la fonction compte_hanoi_na f quoique parfaitement correcte d un point de vue math matique n aurait pas pu nous fournir le r sultat pour 64 En effet cette version calcule son r sultat en utilisant uniquement l addition Plus pr cis ment elle n ajoute toujours que des 1 il lui aurait donc fallu faire 264 1 ad ditions M me en supposant qu on fasse 1 milliard d additions par seconde ce qui est la limite de
275. e de donn es ce petit jeu Caml Light se r v le nettement plus lent que des compilateurs traditionnels Caml Light produit du code pour une machine virtuelle code qui est en suite interpr t alors que les compilateurs traditionnels produisent du code directement ex cutable par la machine En ce cas on gagne beaucoup utiliser un compilateur Caml produisant du code machine optimis tel que le compilateur Objective Caml Bibliographie Pour une bonne pr sentation des automates vus sous un angle pratique on se re portera au chapitre 3 de Compilateurs principes techniques et outils de Aho Sethi et Ullman Inter ditions Pour les lecteurs que les math matiques n effraient pas sig nalons que les automates ont beaucoup t tudi s dans le cadre des langages formels une des branches les plus anciennes de l informatique th orique Le livre de Aho et Ullman Theory of parsing translation and compiling 1 parsing Addison Wesley en donne une bonne vue d ensemble III Introspection 17 Ex cution d un langage fonctionnel Quand Caml se regarde le nombril ou commence tenir ses lacets de chaussures ORTS DE L EXP RIENCE acquise avec l impl mentation du mini Pascal chapitre 15 nous entamons ici la description et l impl mentation d un langage fonctionnel simplifi qui est en r alit un sous ensemble de Caml et que nous nommerons mini Caml Comme d habitude nous essaierons de ne pas
276. e de liste d l ments La syntaxe des d finitions de tableaux est la suivante Tableaux expression expression Nous utilisons ici un nouveau symbole pour la description des constructions syntax iques qui acceptent les r p titions l toile La formule quelque chose signifie la r p tition de quelque chose un nombre quelconque de fois y compris z ro fois si n cessaire ce qui correspond alors ignorer compl tement quelque chose Nous in diquons ainsi que le premier l ment du tableau est ventuellement suivi d autres l ments en nombre quelconque s par s par des points virgules La syntaxe de l affectation et de l acc s aux l ments de tableaux est la suivante Acc s dans un tableau vect indice Modification d un l ment de tableau vect indice lt expression Attention la signification des parenth ses dans cette description Elles font ici partie de la syntaxe d crite il faut les crire dans les programmes alors que dans la notation expression les parenth ses nous servaient regrouper les constructions syntax iques et expression La diff rence de nature des parenth ses se traduit par un changement de police de caract res 3 4 Impression des polyn mes Nous savons maintenant repr senter les polyn mes l aide des tableaux Pour les manipuler nous savons parcourir leurs coefficients l aide d une boucle for Nous pou
277. e f o g en math matiques prononcer f rond g est la fonction h d finie par h x f g x On fait souvent le sch ma suivant Composition de fonctions 71 Ainsi l op rateur o des math matiques est une fonctionnelle qui prend deux fonctions en arguments et renvoie une fonction leur compos e Il n y a pas de difficult s d finir l op rateur o en Caml nous l impl mentons sous le nom de compose let compose f g function x gt f g x compose a gt b gt c gt a gt c gt b lt fun gt Le type de la fonction compose refl te fid lement les restrictions qu on doit imposer deux fonctions pour pouvoir effectivement les composer D ailleurs ces restrictions apparaissent dans notre sch ma il faut que l ensemble de d part de la fonction f soit le m me que l ensemble d arriv e de la fonction g De plus par d finition la compos e fogde f et de g a pour ensemble de d part celui de g et pour ensemble d arriv e celui de f On le constate graphiquement si l on ne fait figurer dans le sch ma de la composition que les ensembles et les fonctions qui interviennent sch ma ci dessous gauche Le contr leur de type de Caml calcule un type o les noms A B C sont remplac s respectivement par les param tres c a et b sch ma de droite fog compose f g A D peo C c p a SS b g f g f Le contr leur de type a donc retrouv tout seul les contraintes math matiq
278. e faisant pointer vers l est en le baissant pour qu il laisse une trace et en amenant le point courant du graphisme de Caml la position actuelle du crayon Enfin et c est le plus difficile on efface l cran La fonction obtient cet effet en peignant tout l cran avec la couleur du fond L cran forme un rectangle de coin inf rieur gauche 0 0 152 et de coin sup rieur droit size_x size y On utilise la fonction pr d finie fill_rect qui remplit un rectangle avec la couleur de trac courante Cette couleur est fix e par la fonction graphique set_color Nous avons choisi les couleurs de fond et de trac comme sur une feuille de papier c est dire blanc pour le fond couleur pr d finie white et noir pour les points trac s couleur pr d finie black let couleur _du_trac black couleur_du_trac color 0 let couleur_du_fond white couleur_du_fond color 1 let z ro_x float_of_int size_x 2 z ro_x float 3000 0 let z ro_y float_of_int size_ y O 2 z ro_y float 2000 0 let vide cran set_color couleur_du_fond fill_rect 0 0 size x size y O set_color couleur_du_trac crayon x lt z ro_x crayon y lt z ro_y crayon vis e lt 0 0 crayon lev lt false moveto round crayon x round crayon y vide_ cran unit gt unit lt fun gt 8 5 Premiers dessins Dessiner un carr avec le crayon est partic
279. e fonction en argument et l appelle sans rien savoir son propos En g n ral lorsque le compilateur produit du code pour une application de fonction il ne conna t pas la d finition de cette fonction ce qui l emp che de faire certaines optimisations simples En particulier une application de fonction plusieurs arguments f e1 en n est g n ralement pas compilable la Pascal en passant les n arguments d un seul coup car rien ne garantit que f soit une fonction n arguments de la forme f z1 n elle pourrait aussi bien tre le r sultat 370 En guise de conclusion d un calcul beaucoup plus compliqu rendant n cessaire de passer les n arguments un par un avec des constructions de fermetures interm diaires pensez map successeur pour une fonction un argument et let f x let in function y gt pour une fonction deux arguments En bref la notion d arit d une fonction est dif ficile d finir en Caml elle ne se d tecte pas directement par le type des fonctions et impose donc une analyse parall le au typage La difficult est encore plus grande si l on souhaite traiter de la m me mani re les fonctions n aires curryf es et les fonctions n aires non curryf es celles dont les arguments sont syntaxiquement sous la forme d un n uplet Les meilleurs compilateurs Caml savent optimiser les appels directs aux deux types de fonctions Cr ation des fermetures En pratiq
280. e fonctions nous avons la convention suivante let fx est quivalent let f function x gt On peut it rer cette convention pour d finir les fonctions plusieurs arguments let fxy est quivalent let f function x gt function y gt Application de fonctions Pour ce qui est de l application de fonction nous avons vu que les parenth ses autour de l argument tait facultatives Si x est une variable ou une constante f x est quivalent f x Attention cette convention n est valable que lorsque x est une variable ou une con stante Si vous employez cette convention avec une expression plus compliqu e les parenth ses retrouvent leur sens habituel en math matiques le groupement des expres sions et la pr sence de parenth ses modifie alors le r sultat du calcul Par exemple l argument n gatif d une fonction doit imp rativement tre parenth s f 1 sans parenth ses est compris comme la soustraction f 1 De m me si l argument est une expression complexe vous ne pouvez pas supprimer les parenth ses sans changer le r sultat successeur 2 3 int 7 16 Premiers pas successeur 2 3 int 9 Cette derni re phrase est comprise par Caml comme si vous aviez crit successeur 2 3 C est d ailleurs un ph nom ne g n ral pour tous les op rateurs de Caml les applications de fonctions en argument des op rations sont implicite
281. e imp ratif Cette d marche n est pas obligatoire l optimisation consiste aussi remplacer un al gorithme du monde fonctionnel par un autre plus efficace mais sans quitter le monde fonctionnel C est ce que nous allons voir maintenant Retournement d une liste La fonction rev est un exemple embl matique de fonction simple qui a pourtant un comportement catastrophique si l on n a pas le souci de r fl chir la complexit de ses programmes La fonction rev renvoie sa liste argument l envers Ici l analyse de complexit nous sugg re un programme fonctionnel bien meilleur On crit une version tr s na ve de rev en se basant sur le raisonnement suivant e Si la liste est vide son envers est aussi vide e Si la liste n est pas vide il suffit d ajouter son premier l ment la fin du reste de la liste l envers Cela se traduit imm diatement par la d finition 102 Listes let rec rev function l gt f x l gt concat ne rev 1 x rev a list gt a list lt fun gt rev 1 2 3 l int list 3 2 1 Cette version est encore plus jolie avec la version infixe pr d finie de concat ne l op rateur let rec rev function 0D gt O x 1 gt rev 1 x rev a list gt a list lt fun gt Cet algorithme est simple le programme extr mement concis mais malheureusement inefficace car on ne cesse de recopier des listes en u
282. e jamais poser un disque sur un disque plus petit que lui et de ne d placer qu un seul disque la fois Au d but du jeu tous les disques sont pos s sur la tige de gauche Le but du jeu est de d placer les disques d une tige sur l autre sans jamais violer la r gle pour finalement les amener tous sur la tige de droite Le jeu original tait accompagn d une notice racontant la l gende de moines d un temple de Hanoi qui passaient leur temps r soudre ce jeu pour atteindre le nirvana En effet les moines croyaient que la fin du monde arriverait lorsque le jeu serait achev Leur jeu grandeur nature occupait la cour d un temple Il se composait de 64 disques d or et de trois tiges d ivoire d un m tre de haut Cette l gende a t invent e par le math maticien fran ais Edouard Lucas en 1883 Notre but est d crire un programme qui indique les mouvements faire pour r soudre le jeu Si vous n tes pas trop impatient cherchez quelques instants vous m me la solution C est difficile n est ce pas Et pourtant ce jeu est trangement facile r soudre avec une proc dure r cursive Les tours de Hanoi 29 D placer les autres disques sur B en respectant la r gle hanoi A C B n 1 B E autres disques plus gros disque A B C D placer le disque restant vers C mouvement C D D autres disques plus gros disque A B C D placer les autres disqu
283. e l utilisateur affichage de r sultats lecture ou criture de fichiers bref tout ce qu on nomme les entr es sorties Toutes ces op rations qui modifient physiquement le contenu des adresses m moire sont appel es effets ou encore effets de bord Un effet est une modification d une case de la m moire tableau ou r f rence ou encore une interaction avec le monde ext rieur impression ou lecture 38 Programmation imp rative Ce style de programmation par effets s appelle la programmation imp rative Ce nom provient videmment de la signification du mode imp ratif dans la conjugaison des verbes En effet les programmes imp ratifs d crivent explicitement la machine la suite des op rations effectuer fais ci fais a Au contraire en programmation fonc tionnelle on laisse la machine calculer le r sultat comme elle le peut partir d une for mule sans lui pr ciser compl tement l ordre dans lequel elle doit op rer Par exemple pour calculer le carr d un nombre x on crit x x en programmation fonctionnelle Au contraire une m thode imp rative serait de r server une case m moire comme ac cumulateur de l initialiser avec x puis de remplacer le contenu de cet accumulateur par son contenu multipli par lui m me Le r sultat cherch serait maintenant dans l accumulateur Dans un cas si simple ces descriptions sont videmment caricaturales mais l id e est la bonne Le style imp rati
284. e paire d entier coefficient degr let abs_mon me function a degr gt if a lt 0 then a degr else a degr abs_mon me int a gt int a lt fun gt Ce code est parfaitement correct mais dans le cas o le coefficient est positif on aimerait rendre directement le mon me re u en argument Le code serait plus clair puisqu il n y aurait pas besoin d une petite gymnastique mentale pour se rendre compte que lexpression a degr correspond exactement au filtre de la clause Autrement dit nous voudrions nommer mon me le filtre a degr et rendre mon me quand a est positif Dans ce cas on introduit le nom choisi avec le mot cl as qui se prononce ase et signifie en tant que en anglais Synonymes dans les filtres filtre as nom Nous obtenons let abs_mon me function a degr as mon me gt if a lt O then a degr else mon me abs_mon me int a gt int a lt fun gt Maintenant le nommage indique l vidence qu aucune transformation n est faite sur le mon me alors que l expression a degr bien qu quivalente cache un peu qu elle n est autre que l argument de la fonction Pour la fonction ins re l usage d un filtre synonyme pour nommer la liste argument clarifie galement un peu le code let rec ins re l ment function O gt l ment x reste as L gt if l ment lt x then l ment 1
285. e pas d algorithme de typage lin aire La taille du type d une phrase comportant n constructions let est susceptible d atteindre 2 Pire si l on ne prend pas soin d imprimer les types avec le partage alors la taille du type produit en nombre de caract res peut atteindre 2 Voici un exemple de programme produisant ce comportement pathologique let paire x function proj gt proj x x paire a gt a gt a gt b gt b lt fun gt let x0 y paire paire y x0 a gt CCa gt a gt b gt b gt a gt a gt b gt b gt c gt c lt fun gt let x1 y x0 x0 y x1 a gt Ca gt a gt b gt b gt Ca gt a b gt b gt 76 gt c gt Ca gt a gt b gt b gt Ca gt a gt b gt b gt c gt c gt d gt d gt Ca gt Na gt b gt Pb gt Ca gt a gt b gt b gt c gt c gt Ca gt a gt b gt b gt Ca gt a gt b gt b gt c gt c gt d gt d gt e gt e lt fun gt Nous n irons pas plus loin sous peine de remplir ce livre avec les types de cette s rie Vous continuerez vous m me avec let x2 y x1 x1 y let x3 y x2 x2 y let x4 y x3 x3 y titre indicatif le type de x2 d passe les 72 lignes de 80 caract res celui de x3 les 18000 l
286. e pr tendre que t n est plus une inconnue puisqu elle a une valeur Voici ce que donnerait une modification h tive de t pour la faire pointer vers t1 Traitement erron de t t t deviendrait cyclique Inconnue 18 4 L unification L unification est le moteur de la r solution des quations de typage Elle consiste r soudre un ensemble d quations en donnant aux variables de type qui interviennent 354 Un synth tiseur de types dans le probl me des valeurs qui rendent toutes les quations vraies tant donn e notre repr sentation des quations l unification revient prendre deux types et les rendre gaux si n cessaire en attribuant des valeurs convenables aux inconnues qui apparaissent dans ces types Le test d occurrence Avant d aborder l unification il nous faut expliquer une derni re subtilit du typage de Caml le test d occurrence Il consiste v rifier qu une inconnue n est pas pr sente dans un type dont elle doit prendre la valeur Cela entre dans le cadre de la pr vention des cycles dans un cas de figure plus subtil que l affectation d une variable elle m me Ce test sert donc garantir que les types manipul s par l algorithme de typage sont toujours des arbres ne comportant pas de cycles En effet notre algorithme bouclerait si les types qui lui sont soumis devenaient cycliques en cours de typage Avant de donner une inconnue la valeur d un t
287. e rose n est ce pas Vous ne devriez pas parler ainsi Quelle tristesse n est ce pas sait sais savoir Est ce vraiment tr s grave l Le savoir est une denr e rare ordinatuer tes vous certain de le savoir Vous voulez dire ordinateur je Ne subsiste t il pas de doute suppose Je ne pourrais pas en dire autant C ordinateur ordinateurs machine Difficile admettre machines En tes vous si s r l Connaissez vous bien l informatique oui Changeons de sujet celui l ne l En tes vous certain m int resse pas Vous tes vraiment s r de vous Ah les machines a ne me semblait pas vident Les machines c est si b te Pourtant j aurais cru le contraire Je connais bien les ordinateurs et C est int ressant continuez j vite de les fr quenter Quelle affirmation sans d tours Je n ai pas d avis sur les machines en Tr s bien g n ral Quel aveu Vous savez je suis une machine moi m me Bon sed C quoi comment C informatique informaticien C est vous de me le dire informaticiens Difficile dire l Quel beau m tier de s occuper des R fl chissez vous comprendrez machines La r ponse est en vous Ah l informatique LC merci remercie L informatique est un dur m tier I Ne me remerciez pas C est difficile l i
288. e sch ma de nommage de ces fonctions qui consiste suffixer le nom print_ par le type de l argument Ainsi la fonction d impression des nombres flottants les valeurs du type float que nous verrons au chapitre 8 s appelle print_float et celle pour les caract res type char s appelle print_char Telle qu elle est crite la fonction compte_ _rebours ne termine pas si on lui passe un argument n gatif la d finition n est donc pas bien fond e Il serait plus s r de remplacer le test n O par le test n lt O Fonctions r cursives simples 23 Par curiosit inversons l appel r cursif et les impressions autrement dit rem pla ons print_int n print_string compte_ _rebours n 1 par compte_ _rebours n 1 print_int n print_string Et afin de ne pas perdre notre fonction pr c dente nous nommons compte cette version modifi e de compte_ _rebours Nous obtenons let rec compte n if n 0 then else begin compte n 1 print_int n print_string end compte int gt unit lt fun gt compte 10 123465678910 unit Cette fonction compte l endroit C est plus difficile comprendre l impression se produit au retour des appels r cursifs On doit d abord atteindre n 0 avant d imprimer le premier nombre qui est alors 1 En effet c est toujours pendant l valuation de compte 1 que nous appelons compte 0 Apr s avoir imprim 1 compte 1 retourne l va
289. e session 143 sys__Break gt message n n nVous pourriez tre poli et me dire au revoir n n n au_revoir cam lia unit gt unit lt fun gt 7 7 Exemple de session Tout est pr t pour qu un des auteurs se fasse soigner cam lia Bonjour je m appelle Cam lia Je suis l pour vous aider r soudre vos probl mes psychologiques Terminez en me disant Au revoir Allons y Parlez moi de vous gt gt J ai des tas de probl mes docteur Quels malheurs sont les v tres gt gt Voil mon petit chat est mort La mort est un sujet tr s grave gt gt Oui je ne me console pas En tes vous certain gt gt Oui Si vous ne m expliquez pas mieux comment vous comprendre gt gt Voil c tait un chat angora vert qui r vait beaucoup la nuit Parlez moi un peu de vous gt gt Ce n est pas le sujet C est mon chat qui m int resse et l informatique videmment Aimez vous vraiment l informatique gt gt a c est s r Surtout quand j arrive faire tourner mes programmes mon avis la programmation c est facile non gt gt Ben pas vraiment si vous voulez savoir Vous ne le pensez pas vraiment gt gt Si bien sur Que pensez vous de l amour gt gt Quoi Il me semblait pourtant avoir t claire gt gt 0K Revenons mes probl mes Je suis malheureux cause de mon chat Racontez moi vos probl mes gt gt Mes enfants ne dorment plus depuis la mort de ce
290. e seule op ration quel que soit son argument En revanche la complexit de la fonction factorielle d pend de son argument elle demande n op rations pour l argument n Plus pr cis ment il faut n multiplications n 1 appels r cursifs la fonc tion factorielle et n soustractions Si l on consid re que ces trois types d op rations ont des co ts voisins alors la complexit de factorielle est de l ordre de 2n n 1 c est dire de l ordre de 3n On consid rera donc que la fonction factorielle a une complexit qui augmente au m me rythme que son argument ce qu on note O n et qu on prononce grand o de n Plus pr cis ment O n signifie un certain nombre de fois n plus des termes n gligeables devant n quand n devient grand comme par exemple une constante On ne s int resse en effet qu un ordre de grandeur de la com 32 R cursivit plexit cette complexit augmente t elle comme l argument algorithme lin aire ou comme le carr de l argument algorithme quadratique ou comme une exponentielle de l argument algorithme exponentiel Dans le cas de factorielle on r sume l tude en notant une complexit lin aire O n puisque la complexit r elle est 3n 1 Principe de r currence Les tudes de complexit et les d finitions r cursives de fonctions reposent sur un raisonnement simple sur les propri t s qui concernent les nombres entiers le principe de r currence Nous all
291. e si le flux contient plus d un l ment La d finition de saute_blancs se lit donc si le premier caract re de flux est un espace motif alors se rappeler r cursivement sur flux faire de m me si le premier caract re de flux est le caract re de tabulation motif t ou le caract re fin de ligne motif n dans tous les autres cas renvoyer On pourrait craindre que les appels r cursifs saute_blancs ne terminent pas puisqu on se rappelle sur le m me argument flux que celui qu on a re u Ce n est pas vrai car le flux a t physiquement modifi entre temps d s qu un des trois premiers motifs s applique le premier l ment du flux est enlev de ce dernier L appel r cursif de saute_blancs s effectue donc sur le reste du flux comme d sir En revanche lorsque les trois premiers motifs ne s appliquent pas parce que le premier caract re du flux n est pas un blanc le premier caract re du flux n est pas supprim le dernier motif tant vide il ne consomme aucun l ment du flux Incidemment une mani re plus compacte d crire la fonction saute_blancs est de regrouper les trois premiers cas comme ceci let rec saute_blancs flux match flux with lt At Mn gt gt saute_blancs flux lt gt gt O saute_blancs char stream gt unit lt fun gt La barre verticale dans les motifs signifie ou Le motif tf n
292. e_string sup rieur ou gal sur les cha nes ou le_string inf rieur ou gal qui comparent deux cha nes dans l ordre lexicographique c est dire l ordre du dictionnaire let t l Salut les copains in tri function x gt function y gt ge_string x y t t string vect l les copains Salut J La pleine fonctionnalit 67 let t l Salut les copains in tri function x gt function y gt le_string x y t t string vect l Salut copains les On constate sur cet exemple que les lettres majuscules pr c dent les lettres minuscules dans l ordre lexicographique utilis en Caml Nous pouvons maintenant appliquer par tiellement la proc dure tri des ordres habituels pour obtenir des proc dures de tri sp cialis es let tri_croissant t tri function x gt function y gt x lt y t tri_croissant a vect gt unit lt fun gt let tri d croissant t tri function x gt function y gt x gt y t tri_d croissant a vect gt unit lt fun gt let tri_du_dictionnaire tri le_string tri_du_dictionnaire string vect gt unit lt fun gt let t Bonjour tout le monde in tri_du_ dictionnaire t t string vect l Bonjour le monde tout En conclusion nous avons pu d finir une proc dure de tri tr s g n rale gr ce au polymorphisme cette proc dure s applique tout
293. ec une fonction locale ne se justifie pas non plus par un gain majeur en efficacit suivant les compilateurs elle sera un peu plus ou un peu moins efficace que la d finition na ve En revanche dans le cas o une fonction r cursive prend beaucoup de param tres en argument et o ces param tres sont inchang s dans les appels r cursifs on peut admet tre de d finir localement une fonction r cursive qui s appelle avec les seuls param tres modifi s En ce cas on remplacerait la d finition d une fonction f plusieurs param tres x1 x2 xn dont les appels r cursifs ne font varier que xn par une d finition com portant une fonction locale ayant xn pour seul param tre Ainsi let rec f x1 x2 x3 xn f x1 x2 x3 xn 1 f x1 x2 x3 xn 1 deviendrait let f x1 x2 x3 let rec f_locale xn f_locale xn 1 f_locale xn 1 in f_locale Ce style ne se justifie que pour des raisons de concision il ne doit pas tre rig en syst me 5 10 Efficacit des fonctions sur les listes tude de cas Dans cette section nous analysons la complexit de deux fonctions implose et rev L tude de complexit nous am ne crire des versions plus efficaces en style imp ratif pour implose et en style purement fonctionnel pour rev L am lioration obtenue est bas e dans les deux cas sur l emploi d un accumulateur qui maintient les r sultats Efficacit des fonctions sur les liste
294. econna tre et la fonction de reconnaissance de ses arguments puis construise automatiquement la fonction reste correspondante C est possible avec la fonctionnelle lire_op ration ci dessous Fichier asynt ml let lire_op ration lire_op rateur lire_base constructeur let rec lire_reste ei function lt lire op rateur _ lire_base e2 lire_reste constructeur ei e2 e gt gt e lt gt gt e1 in function lt lire_base ei lire_reste ei e gt gt e L argument lire_op rateur est une fonction qui reconna t les flux commen ant par l op rateur qui nous int resse par exemple function lt MC gt gt dans le cas de l op rateur L argument lire_base est une fonction suppos e re conna tre les arguments de l op rateur Enfin l argument constructeur est une fonc tion qui re oit les arbres de syntaxe abstraite des arguments et doit construire l arbre de syntaxe abstraite de l expression tout enti re En utilisant cette puissante fonctionnelle lire_op ration l analyseur syntaxique se simplifie notablement Fichier asynt ml let rec lire_proposition f propositions f and proposition0O function lt Ident s gt gt Variable s lt MC vrai gt gt Vrai lt MC faux gt gt Faux lt MC lire_proposition p MC gt gt p and propositioni function lt MC non proposition0 p gt gt Non p
295. ection Effets et valuation qui s ouvre par un avertissement au d butant Cette section peut tre saut e en premi re lecture La d marche que nous avons adopt e c est dire l apprentissage par des exemples int ressants nous a conduits pr senter les notions du langage par n cessit nous les expliquons lorsqv elles interviennent et uniquement l Il se peut donc que certaines notions inutiles nos programmes ne soient pas pass es en revue Cela indique claire ment qu elles ne sont pas essentielles Si l on d sire absolument une vue exhaustive des possibilit s de Caml on consultera le Manuel de r f rence du langage Caml auquel nous avons d j fait allusion 1 Premiers pas O l on v rifie que 2 et 2 font 4 I VOUS SAVEZ D J que 2 2 font int 4 et que let f function x gt signifie let f x vous pouvez sauter ce chapitre Sinon il vous initiera l interaction avec Caml 1 1 Id es g n rales sur Caml Caml est un langage simple il y a peu de constructions mais ces constructions sont les plus g n rales possibles Caml utilise des notations intuitives ou consacr es par l usage et souvent proches de celles des math matiques Par exemple pour ajouter 1 et 2 il suffit d crire 1 2 Et les cha nes de caract res c est dire les textes qui ne doivent pas tre interpr t s par le langage sont crites entre des guillemets not
296. elle de la fonction ex cute_ordre non pas l environnement courant mais celui ad quat l ex cution du corps de la proc dure do_list ex cute_ordre env_pour_corps corps L valuation des programmes Les phrases de notre mini Logo sont soit des d finitions de proc dures soit des ordres Un programme est une suite de phrases type phrase_logo Pour of string proc dure Ordre of ordre Le type phrase_logo est d fini type programme_logo Programme of phrase_logo list Le type programme_logo est d fini On ex cute un ordre en appelant la fonction ex cute_ordre dans un environ nement initialement vide tandis qu une d finition se contente d appeler la fonction d finit_proc dure let rec ex cute_phrase function Ordre ord gt ex cute _ ordre ord Pour nom proc as liaison gt d finit _ proc dure liaison and ex cute_programme function Programme phs gt do_list ex cute_phrase phs ex cute_phrase phrase_logo gt unit lt fun gt ex cute_programme programme_logo gt unit lt fun gt L analyseur syntaxique L analyseur syntaxique est tr s semblable celui de la section 9 6 il est seule ment un peu plus long Nous avons regroup les clauses analogues dues aux mots cl s synonymes l aide de filtres ou par exemple lt Mot baisse_ crayon Mot bc gt gt Bc Remarquez aussi que les expressions alors et sinon de l alter
297. elle on utilise la fonction pr d finie raise en anglais to raise signifie lever raise exn gt a lt fun gt raise chec_de_t te Exception non rattrap e Failure t te La primitive raise est une fonction magique car elle n est pas d finissable dans le langage Elle interrompt imm diatement les calculs en cours pour d clencher le signal lever la valeur exceptionnelle qu elle a re u en argument C est ce qui explique qu un appel la fonction raise puisse intervenir dans n importe quel contexte avec n importe quel type les calculs ne seront de toute fa on jamais effectu s lorsqu on valuera l appel raise le contexte peut donc faire toutes les hypoth ses qu il d sire sur la valeur renvoy e par raise Par exemple 1 raise chec_de_t te Exception non rattrap e Failure t te Bonjour raise chec_de_t te Exception non rattrap e Failure t te Bien entendu les phrases essentiellement mal typ es o raise appara t dans un con texte lui m me mal typ sont toujours rejet es 128 Le docteur 1 raise chec_de_t te Bonjour Entr e interactive gt 1 raise chec_de_t te Bonjour Cette expression est de type int mais est utilis e avec le type string La construction try with On peut donc consid rer les valeurs exceptionnelles comme des signaux qu on envoie l aide de la fonction raise et qu o
298. end let res tampon val land 1 in 252 Compression de fichiers tampon val lt tampon val lsr 1 tampon nbits lt tampon nbits 1 res Les op rateurs infixes land et 1sr sont respectivement le et bit bit entre entiers et le d calage logique droite 13 5 Mise en pratique Tous les modules du programme sont maintenant crits il reste les compiler et les lier entre eux camlc c esbit mli camlc c esbit ml camlc c fileprio mli camlc c fileprio ml camlc c huffman mli camlc c huffman ml camlc c compr ml camlc o compr esbit zo fileprio zo huffman zo compr zo lt R e A A Pour essayer le programme camlrun compr monfichier camlrun compr d monfichier cpr Une autre mani re de proc der est de compiler le programme partir du syst me interactif avec les commandes compile et load_object comme d crit au chapitre 10 section 10 6 La compression s effectue alors par compr__compresse_fichier fich et la d compression par compr__d compresse_fichier fich cpr 13 6 Pour aller plus loin L algorithme de Huffman employ ici n est certainement pas le meilleur algorithme de compression existant l heure actuelle Outre un taux de compression pas tr s lev il pr sente deux inconv nients pratiques le fichier compress doit contenir l arbre de Huffman construit au codage et le fichier d entr e doit tre lu deux fois Le premier trait est g na
299. end naturellement aux enregistrements let de_degr _z ro function degr 0 coefficient _ gt true _ gt false de_degr _z ro mon me gt bool lt fun gt de_degr _z ro ml bool true Il existe en plus une ellipse sp ciale pour indiquer qu on ne s int resse pas au reste des champs d un enregistrement on crit _ pour dire quels que soient les autres champs et leurs contenus On crirait donc la fonction de_degr _z ro plus naturelle ment ainsi let de_degr _z ro function degr 0 _ gt true _ gt false de_degr _z ro mon me gt bool lt fun gt On peut aussi nommer le contenu des champs et faire des synonymes Par exemple la fonction qui renvoie la valeur absolue d un mon me s crit let abs_mon me function coefficient a degr d as m gt if a lt O then coefficient a degr d else m abs_mon me mon me gt mon me lt fun gt Les types enregistrement portent le nom technique de produits nomm s champs nomm s et les types produit en g n ral correspondent la notion math matique de produit cart sien d ensembles Encore une fois nous nous contenterons de la vision intuitive 118 Les structures de donn es 6 5 M lange de types somme et types produit Types somme et types produit peuvent tre arbitrairement m lang s Ainsi une d finition plus labor e des polyn mes serait type poly
300. enne dans le style function x gt conduirait crire let moyenne function a gt function b gt a b 2 moyenne int gt int gt int lt fun gt Au passage nous remarquons qu une fonction anonyme a parfaitement le droit d avoir plusieurs arguments Attention il n est pas permis d crire function a b gt il faut imp rativement r p ter le mot cl function une fois par argument C est pourquoi nous utiliserons la plupart du temps le style le plus l ger celui qui vite d employer le mot function Les tests et l alternative Caml fournit une construction pour faire des calculs qui d pendent d une condi tion c est l alternative le classique if then else Cette construction correspond au calcul si condition alors expression sinon expression gt qui signifie simplement qu il faut calculer expression si la condition est vraie et expression sinon Nous illustrons cette construction en impl mentant c est dire en r alisant sur ma chine la fonction valeur absolue qui calcule la valeur d un nombre ind pendamment de son signe Cette fonction not e x en math matiques est d finie comme x six gt 0 z x sinon Sachant qu en Caml les comparaisons entre nombres entiers suivent les notations math matiques lt gt gt et lt nous sommes arm s pour d finir la fonction valeur absolue let valeur_absolue x if x gt
301. entation du filtrage Cette op ration prend une valeur et un motif et d termine si la valeur est de la forme indiqu e par le motif Si la r ponse est non elle d clenche l exception chec_filtrage Si la r ponse est oui elle renvoie un ensemble de liaisons d identificateurs les variables du motif des valeurs les morceaux correspondants de la valeur d entr e repr sent es par une liste de paires identificateur valeur Fichier eval ml open syntaxe exception chec_filtrage L valuateur 329 let rec filtrage valeur motif match valeur motif with val Motif_variable id gt id val Val_bool enne bi Motif_bool en b2 gt if b1 b2 then else raise chec_filtrage Val_nombre ii Motif _nombre i2 gt if il i2 then else raise chec _filtrage Val_paire vi v2 Motif _paire mi m2 gt filtrage vi mi filtrage v2 m2 Val_nil Motif _ nil gt Val_cons vi v2 Motif_cons mi m2 gt filtrage vi mi filtrage v2 m2 _L _ gt raise chec_filtrage La fonction d valuation d une expression est remarquablement concise D taillons en les principales clauses L environnement d valuation est repr sent par une liste d association entre les identificateurs et leurs valeurs Ceci explique la clause des variables Pour les fonctions on se contente de cr er une fermeture qui emmaga sine l environnement courant env au moment de l
302. er compil ml open syntaxe open envir open printf let taille_du_mot 4 un mot quatre octets let rec taille_du_type function Integer Boolean gt taille_du_mot Compilation 291 Array inf sup ty gt sup inf 1 x taille_du_type ty La fonction val_const traduit une constante en l entier qui la repr sente Fichier compil ml let val_const function Enti re n gt n Bool enne b gt if b then 1 else O Environnements de compilation Les fonctions de compilation prennent en argument un environnement qui indique quels emplacements m moire se trouvent les variables On r utilise la structure g n rique d environnement fournie par le module envir Les donn es associ es aux noms de variables sont du type info_variable d fini ci dessous Fichier compil ml type info_variable typ expr_type emplacement emplacement _variable and emplacement_variable Global_indirect of int Global_ direct of int Local_indirect of int Local_direct of int Le compilateur attribue une adresse absolue chaque variable globale Cette adresse est l argument des constructeurs Global_direct et Global_indirect La distinction entre ces deux constructeurs est la suivante si la variable est un entier ou un bool en l entier associ est l adresse d un mot qui contient la valeur courante de x En revanche si la variable est un
303. ertains de ces arguments se justifie lorsque la fonction est tr s g n rale Dans ce cas cette op ration de sp cialisation permet de retrouver des fonctions int ressantes en elles m mes Nous en verrons un exemple avec le tri o fixer l argument fonctionnel correspondant la comparaison permet de d finir le tri en ordre croissant ou le tri en ordre d croissant De cette tude des fonctions curryfi es retenons que le constructeur de type est associatif droite ce qui signifie tout simplement que ti t2 t3 est quivalent t t2 t3 4 5 Une fonctionnelle de tri polymorphe Le polymorphisme n est pas r serv au style fonctionnel Pour le montrer nous d finissons ici une proc dure qui trie en place un tableau La proc dure ne calcule pas de valeurs mais modifie l ordre des l ments dans le tableau Nous g n ralisons ensuite cette proc dure pour la rendre applicable tout type d ordre Trier des tableaux en ordre croissant L algorithme de tri employ ici repose sur une id e tr s simple on cherche le mini mum des l ments du tableau et on le met la premi re place Puis on cherche le min imum du reste du tableau et on le met la seconde place Il suffit d it rer ce proc d jusqu avoir parcouru compl tement le tableau Ce tri s appelle le tri par s lection Son principe s illustre graphiquement par le sch ma suivant qui montre la 4 tape du tri par s
304. es de B vers C en respectant la r gle hanoi B A C n 1 ES CE autres disques plus gros disque A B C autres disques C plus gros disque A B C Figure 2 1 Comment r soudre le probl me des tours de Hanoi 30 R cursivit Le programme Supposons que les tiges s appellent A B et C que n soit le nombre de disques tous pos s au d part sur la tige A et que nous devions les mettre sur la tige C L astuce consiste se rendre compte que si nous savions comment r soudre le probl me pour n 1 disques alors nous saurions le faire pour n sans violer la r gle En effet si l on suppose les n 1 disques d j pos s sur la tige B le dernier disque encore pos sur la tige A est le plus gros disque Il nous suffit donc de le poser sur la tige C qui est vide pas de violation possible de la r gle puis de d placer les n 1 disques de la tige B la tige C C est possible puisque nous supposons savoir comment d placer n 1 disques d une tige une autre et puisque c est le plus gros disque qui est maintenant pos sur C il n y a pas de violation de la r gle en posant les n 1 disques de B sur la tige C voir la figure 2 1 Mais nous savons aussi r soudre le probl me pour 0 disques il n y a rien faire Nous savons donc r soudre le probl me des tours de Hano pour tout n C est encore plus facile dire en Caml nous d finissons d abord une fonction aux
305. es encore plus complexes 13 2 Plan du programme Nous allons programmer la commande compr qui compresse les donn es des fichiers qu elle traite Les fichiers compress s sont renomm s en ajoutant le suffixe cpr leur nom Quand on l appelle avec l option d la commande compr d compresse les fichiers qu on lui donne en argument Nous commen ons par une fonction commune la compression et la d compression qui se charge d ouvrir les fichiers et d afficher les erreurs d entr e sortie Cette t che conceptuellement simple est en pratique fort encombr e par la r cup ration et l affichage des erreurs c est le prix payer pour obtenir des programmes qui r agissent bien face aux situations exceptionnelles Fichier compr ml open sys exception Erreur let traite_fichier traitement nom_entr e nom_sortie let entr e try open_in_bin nom_entr e with Sys_error message gt prerr_endline Erreur l ouverture de nom_entr e message raise Erreur in let sortie try open_out_bin nom_ sortie with Sys_error message gt close_in entr e prerr_endline Erreur la cr ation de message nom_sortie raise Erreur in try traitement entr e sortie close_in entr e close _out sortie remove nom_entr e with Sys_error message gt close_in entr e close_out sortie remove nom_sortie prerr_endline Erreur pendant le traitement de nom_entr
306. es fichiers d impl mentation ml sont compilables dans n importe quel ordre si un module utilise un module B on peut tr s bien compiler l impl mentation de A avant l impl mentation de B il suffit que l interface de B ait d j t compil e C est le cas dans la s quence de compilation ci dessous camlc c langage mli camlc c crayon mli camlc c langage ml camlc c alex mli camlc c asynt mli camlc c logo ml camlc c asynt ml camlc c crayon ml camlc c alex ml lt A A A On a choisi d crire et de compiler d abord les impl mentations de langage et de logo qui repr sentent le c ur du syst me et de repousser plus tard l criture de asynt m1 alex ml et crayon m1l Plus g n ralement l introduction d interfaces explicites pour les modules permet de se lib rer du style d criture des programmes strictement ascendant bottom up en anglais que nous avons utilis jusqu ici Par la suite nous utiliserons des interfaces chaque fois que nous avons besoin d un module de fonctions auxiliaires dont nous pr f rons cependant repousser l impl mentation plus tard 10 6 Compilations interactives Le compilateur ind pendant n est pas le seul moyen de compiler des fichiers le syst me interactif fournit lui aussi des commandes pour compiler des fichiers compile et charger et ex cuter du code compil 1oad_object La commande compile monfichier ml compile le fic
307. es r sultats assez bien r partis Au dessus de cette fonction il est facile de d finir une fonction de hachage qui op re sur tous les types de cl s let hache taille _ table cl hashtbl__hash cl mod taille table hache int gt a gt int lt fun gt Pour aller encore plus loin le hachage 235 Ensuite on construit facilement un type t et des op rations new add et find compa rables ceux du module hashtbl type Ca b t a x b list vect Le type t est d fini let new taille_ table make_vect taille_table l new int gt a list vect lt fun gt let add table cl donn e let index hache vect_length table cl in table index lt cl donn e table index add a b list vect gt a gt b gt unit lt fun gt let find table cl let index hache vect_length table cl in assoc cl table index find a b list vect gt a gt b lt fun gt L impl mentation du module hashtb1 fournie par la biblioth que standard s appuie elle aussi sur la fonction hash polymorphe mais est plus complexe que l impl mentation donn e ci dessus En particulier elle sait agrandir dynamiquement la table quand les sous ensembles menacent de devenir trop gros ce qui garantit de bonnes performances m me sur de tr s grosses tables 13 Compression de fichiers O l on fait passer un chameau par le chas d une aigui
308. es v prog_proc dures p prog_fonctions f prog_corps i let lire_programme flux lire_prog analyseur_lexical flux 15 2 Typage Nous programmons maintenant un v rificateur de types pour les programmes mini Pascal Le but premier du v rificateur de types est de garantir l absence d incoh rences entre les types des objets manipul s par le programme par exemple l addition d un entier et d un tableau doit tre rejet e Un but secondaire est de d tecter certaines op rations comme l affectation entre tableaux ou le renvoi d un tableau comme r sultat d une fonction op rations que nous avons d cid d interdire pour faciliter la compilation du langage De mani re g n rale les erreurs de types peuvent tre d tect es ou bien au moment de l ex cution typage dynamique ou bien avant l ex cution par une analyse pr alable du programme typage statique Le typage statique offre plusieurs avantages par rap port au typage dynamique Tout d abord il d tecte les erreurs de types dans toutes les branches du programme m me celles qui ne sont pas toujours ex cut es De plus dans le cadre d un compilateur le typage statique nous autorise produire du code ne contenant aucun test sur le type des objets puisqu il garantit que les objets manipul s pendant l ex cution seront forc ment du bon type pour les op rations effectu es dessus Au contraire pour faire du typage dynamique il faudrait produi
309. est un mot cl Les analyseurs lexicaux engendr s par la fonction construire_analyseur savent reconna tre les nombres entiers les identificateurs et les mots cl s Il serait facile d ajouter les nombres flottants et les cha nes de caract res mais cela n est pas utile pour l utilisation que nous en ferons Fonctions de lecture de base Pour la lecture des entiers et des identificateurs nous r utilisons les fonctions lire_entier et lire_mot du mini Logo Fichier lexuniv ml let rec lire_entier accumulateur flux match flux with lt 0 9 as c gt gt lire_entier 10 accumulateur int_of_char c 48 flux K3 gt accumulateur let tampon make_string 16 let rec lire_mot position flux match flux with lt gt A ZS af 2 0 9 a l amp l t 6 l J I I T Pour aller plus loin l analyseur lexical universel 229 if position lt string_length tampon then tampon position lt c lire_mot position 1 flux lt gt gt sub_string tampon O min position string_length tampon Sur le mod le de lire_mot nous ajoutons une fonction lire_symbole qui reconna t les suites de caract res sp ciaux comme ou lt gt Ces suites de caract res sp ciaux sont soit des mots cl s soit des identificateurs exactement comme les suites de lettres et de chiffres qui constituent un
310. est_un_op rateur op rateurs function MC op gt mem op op rateurs l gt false let lire_op rateur op rateurs function lt stream_check est_un_op rateur op rateurs MC op gt gt op let lire_op ration lire_base op rateurs let rec lire_reste e1 function lt lire_op rateur op rateurs op lire_base e2 lire_reste 0p_binaire op ei e2 e gt gt e lt gt gt e1 in function lt lire_base ei lire_reste ei e gt gt e La fonction lire_op rateur prend en argument une liste d op rateurs repr sent s par des cha nes de caract res comme et rend un analyseur reconnaissant les flux qui commencent par un de ces op rateurs La fonctionnelle lire_op ration prend en arguments un analyseur pour les expres sions simples et une liste d op rateurs et reconna t les applications de ces op rateurs des expressions simples Par exemple lire_op ration function lt Entier n gt gt Constante Enti re n peman renvoie un analyseur de type lex me stream gt expression reconnaissant des ex pressions comme 1 2 3 En appliquant cet analyseur au flux Syntaxe abstraite syntaxe concr te 281 lt Entier 1 MC Entier 2 MC Entier 3 gt on obtient l expression Op_binaire Op_binaire Constante Enti re 1 Constante Enti re 2 Constante Enti re 3 Pour construire l arbre de syntaxe on consid re que
311. eur Cette section d crit l architecture et le langage du processeur que nous simulons Nous l appellerons le pico processeur car il est encore plus simple que la plupart des micro processeurs actuels Sous ses airs de simplicit le pico processeur reste n anmoins tr s proche de certains processeurs RISC bien connus tels que l Alpha ou le MIPS Architecture Vu du programmeur le pico processeur se compose d un ensemble de 32 reg istres d une m moire de code dans laquelle est stock le programme ex cuter et d une m moire de donn es dans laquelle le programme peut stocker des r sultats interm diaires Chaque registre contient un mot machine que nous prenons de m me taille que les entiers de Caml Light type int c est dire 31 bits La plupart des machines actuelles 256 Simulation d un processeur Registres M moire de donn es M moire de code 0 Adresse 0 Adresse 0 instruction 0 Adresse 4 Adresse 4 instruction 1 Adresse 8 Adresse 8 instruction 2 registre 31 Figure 14 1 Le mod le du programmeur de la pico machine emploient des mots de 32 bits les mots de 31 bits sont irr alistes mais simplifient consid rablement la simulation Les registres sont num rot s de 0 31 Ils sont interchangeables en ceci que n importe quel registre peut tre argument ou r sultat de n importe quelle op ration il n y a pas de registre sp cifique telle ou telle op ration Cependant
312. eur de th or mes se pr sentant sous la forme d une boucle d interaction qui lit des propositions et essaye de les prouver Le c ur du d monstrateur est la fonction examine Partant d une cha ne de caract res elle la transforme en proposition calcule ses variables libres et appelle v rifie tautologie Si rien ne se passe la proposition est un th or me et la fonc tion examine affiche un message pour le dire Sinon v rifie_tautologie d clenche l exception R futation et examine imprime une r futation prouvant que la proposition fournie n est pas un th or me Fichier demo ml open prop open asynt let examine cha ne let proposition analyse_proposition cha ne in let variables variables_libres proposition in try v rifie_tautologie proposition variables begin match variables with 0 gt 222 D monstration de propositions print_string Th or me var gt print_string Th or me pour toute proposition var _ gt print_string Th or me pour toutes propositions do_list function var gt print_string var variables end print_string cha ne print_newline with R futation liaisons gt LLES print_string cha ne n est pas un th or me n print_string car la proposition est fausse quand n do_list function var b gt print_string var est print_string if b then vraie else fausse print _newline liai
313. eur taille du corps de la fonction fait r f rence celui qui tait d fini au moment de la cr ation de la fonction pas celui qui est d fini quand on appelle la fonction En port e dynamique la valeur des identificateurs correspond leur derni re d finition au cours des calculs La valeur de l identificateur taille aurait donc t modifi e m me dans le corps de la fonction ajoute_taille Notre valuateur simule parfaitement ce comportement statique en attachant au code des fonctions leur environnement de d finition Les lecteurs attentifs auront sans doute remarqu qu une certaine forme de port e dynamique peut tre simul e en Caml l aide de r f rences let taille ref 1 taille int ref ref 1 let ajoute_taille x x ltaille ajoute_taille int gt int lt fun gt taille 2 unit ajoute_taille O int 2 La liaison de taille la r f rence est trait e en port e statique mais le contenu de la r f rence est modifiable apr s la liaison Cette astuce va m me jusqu la d finition de fonctions r cursives sans utiliser let rec la mani re des langages avec port e dynamique let fact let rien ref function x gt x in let f x if x O then 1 else x rien x 1 in rien f f fact int gt int lt fun gt fact 10 int 3628800 Le code de l valuateur La premi re partie de l valuation est consacr e l impl m
314. eux 1 Creux 1 gt Creux multiplie _polyn mes_ creux 1 1 Plein v Creux 1 gt Types sommes labor s 113 Creux multiplie _polyn mes_creux plein_vers_ creux v 1 Creux 1 Plein v gt multiplie_polyn mes p2 pi multiplie_polyn mes polyn me gt polyn me gt polyn me lt fun gt imprime polyn me multiplie polyn mes p1 p2 1 2x 3x 2 x 100 2x 101 3x 102 unit let p10000 Creux 1 0 1 10000 p10000 polyn me Creux 1 0O 1 10000 imprime_polyn me multiplie_polyn mes p10000 p10000 1 2x 710000 x 20000 unit 6 2 Types sommes labor s Un autre exemple classique de type somme est la mod lisation des peintures On suppose que les peintures sont d crites soit par un nom explicite soit par un simple num ro de r f rence soit par un m lange d autres peintures Nous envisagerons succes sivement ces trois cas et construirons donc le type peinture par raffinements successifs en trois tapes Enum rations On consid re d abord les peintures explicitement nomm es en supposant qu il en existe trois le Bleu le Blanc et le Rouge Le type peinture comporte donc trois cas c est un type somme Ces cas ne sont plus des valeurs de types diff rents comme pour les polyn mes mais simplement trois constantes On les mod lise par trois constructeurs sans arguments donc sans partie of dans la d finition type peinture Bleu Bl
315. ex avec d placement constant et index avec d placement calcul Les instructions de branchement sont au nombre de trois On a d une part deux branchements conditionnels braz et branz qui testent si un registre est nul ou non nul et sautent le cas ch ant une adresse donn e On dispose aussi d un branchement inconditionnel jmp une adresse constante ou calcul e contenue dans un registre De plus jmp crit l adresse de l instruction qui le suit dans un registre Ceci permet de 258 Simulation d un processeur faire facilement des appels de sous programmes voir ci dessous Enfin nous avons ajout deux instructions sp ciales qui n ont pas toujours d quivalent dans les processeurs r els mais qui sont tr s utiles dans le cadre d un simulateur stop qui arr te l ex cution du programme et scall pour system call appel syst me qui repr sente l appel un hypoth tique syst me d exploitation en particulier pour faire des entr es sorties Nous utiliserons deux appels syst me l un qui affiche l cran le nombre contenu dans le registre r 1 l autre qui lit un nombre au clavier et le place dans r 1 Idiomes de programmation Le lecteur habitu aux architectures CISC complex instruction set computer pro cesseur jeu d instructions complexe comme par exemple le Pentium d Intel a sans doute t surpris par la pauvret du jeu d instructions du pico processeur En partic ulier
316. explications sur le probl me pr cis qui nous int resse et sur les techniques exactes que nous appliquerons mais nous supposerons connue la probl matique d ensemble Nous utiliserons la pr sentation suivante pour les programmes Caml les interfaces et les impl mentations des modules sont entrem l es avec nos commentaires chaque morceau de code Caml est surtitr par le nom du fichier auquel il appartient Par exemple voici un morceau du fichier toto ml Fichier toto ml let x 1 2 206 Avertissement On reconstitue le programme tout entier en recollant tous les morceaux de fichiers dans leur ordre d apparition la fin de chaque chapitre on explique comment compiler et ex cuter le programme complet Comme pour la premi re partie tous les exemples pr sent s ont t automatique ment extraits du texte puis compil s et ex cut s Enfin ces exemples sont disponibles sur le Web l adresse suivante http caml inria fr Examples 12 D monstration de propositions Mais ou et donc or ni car non si alors X A R CANISER en partie le raisonnement math matique et transformer ainsi les ordinateurs en outils d aide la d monstration de th or mes est l un des plus vieux projets de l informatique Dans ce chapitre nous programmons un d monstrateur pour une classe restreinte de th or mes les formules propositionnelles du premier ordre Ce chapitre constitue galement une initiation la
317. expression e2 gt gt Quotient e e2 lt gt gt e and liste_d expressions function lt expression exp liste_d expressions 1 gt gt exp 1 lt gt gt l La fonction principale logo combine analyse lexicale analyse syntaxique et valuation pour ex cuter un programme lu dans une cha ne de caract res let logo cha ne do_list ex cute_phrase analyse_programme analyseur_lexical stream_of_string cha ne logo string gt unit lt fun gt SE SZ A Voici en guise d exemple les d finitions successives de deux proc dures suivies d une suite d ordres logo pour carr c r p te 4 av c td 90 pour multi_carr c n r p te n carr c td 10 ve multi_carr 80 10 unit Remarquez que nous devons crire 10 avec un blanc entre le z ro et le point car sinon l analyseur lexical croirait avoir affaire un nombre flottant Un peu plus difficile maintenant une proc dure r cursive spirale qui s arr te lorsqu elle a t appel e n fois et qui fait avancer le crayon de la distance d en tournant de l angle a chacune de ses invocations La proc dure s appelle r cursivement avec une distance augment e de l argument i qui est donc l incr ment ajout la distance que parcourra le crayon la prochaine tape logo pour spirale d a i n si n gt 0 av d td a spirale d i a i C n 1 stop
318. f c couleur_d atout then 20 else 2 Petite_carte 10 _ gt 10 Petite_carte 9 c gt if c couleur_d atout then 14 else 0 Fe valeur_d une_carte couleur gt carte gt int lt fun gt Remarquez que la structure du filtrage de la fonction valeur_d une_carte est tr s similaire la d finition du type carte C est un m canisme fr quent en Caml pour d finir une fonction sur un type somme on se guide souvent sur la d finition du type qui donne le squelette du filtrage utiliser On le compl te alors pour envisager les cas particuliers comme ici les cas du 10 et du 9 Cela termine les exemples de types somme Nous donnons maintenant une pr sentation plus g n rale du concept 116 Les structures de donn es 6 3 Les types somme Les types somme servent donc mod liser des donn es comprenant des alternatives On les appelle aussi types ou car une donn e mod lis e par un type somme est d une esp ce ou d une autre ou Par exemple une peinture est soit nomm e soit un simple num ro soit un m lange de deux peintures de m me les polyn mes sont soit pleins soit Creux Les fonctions d finies sur un type somme op rent g n ralement par filtrage sur les l ments du type elles ont une structure tr s voisine de la d finition du type On peut consid rer qu on emploie alors une programmation dirig e par le filtrage ou dirig e par les d finitions de type Remarquons qu il es
319. f implique la modification de l tat de la m moire donc l utilisation de structures de donn es modifiables par exemple les tableaux dont les l ments peu vent tre chang s dynamiquement et l emploi de commandes Les commandes sont des expressions qui ne retournent pas de valeurs int ressantes leur r sultat est simplement une modification de l tat courant c est dire un effet Lorsqu une fonction se contente d ex cuter une s rie de commandes on l appelle souvent proc dure Une proc dure en Caml est donc simplement une fonction qui se contente de faire des effets sans produire de r sultat au sens math matique Nous aurions pu nous cantonner au sous ensemble fonctionnel de Caml et cependant crire de tr s jolis programmes Mais c e t t donner une fausse image de Caml ce qui fait la puissance du langage c est justement qu il ne se limite pas la programmation fonctionnelle mais int gre harmonieusement programmation fonctionnelle et program mation imp rative De plus nous cherchons avant tout vous montrer les programmes les plus simples et les plus clairs possibles nous avons donc besoin de tous les outils que Caml met notre disposition De surcro t la programmation imp rative n est pas seulement indispensable pour traiter les probl mes d interaction avec le monde ext rieur entr es sorties Dans cer tains cas un algorithme c est dire une m thode de r solution d un probl
320. fie function x gt f x en f et l on obtient letg f Vous pouvez constater que nous avons ici raisonn sur un petit programme ind pendamment de sa signification on ne sait pas ce que fait f ni pourquoi on d finit g C est une force de conna tre ce genre de raisonnements tr s g n raux qui s appliquent dans toutes les situations Nous n irons pas plus loin dans ces consid rations un peu complexes et formelles La r gle n restera notre seule r gle de calcul sur les programmes Son nom grec ne doit pas effrayer car la r gle est intuitivement tr s naturelle elle stipule simplement que la fonction qui z associe f x est la fonction f et r ciproquement 3 10 Effets et valuation Cette section peut tre saut e en premi re lecture Effets et appels de fonctions Avec les effets nous sortons du monde intemporel des math matiques pour entrer dans un monde qui conna t les notions de pass et d avenir et dans lequel l enchev trement des calculs a son importance Pour calculer une expression sans effets comme 1 2 3 4 peu importe l ordre dans lequel on effectue les calculs qu on commence par calculer 1 2 ou 3 4 le r sultat est identique Il n en va pas de m me si l on m lange calculs et effets Pour mettre ce ph nom ne en vidence ajoutons des effets dans le calcul de 1 x 2 3 4 en y m lant des impressions au terminal Rempla ons d abord les nombres par des s quences qui les impr
321. fonction manipule des valeurs entiers cha nes de caract res bool ens qui ont toutes un type la fonction elle m me est une valeur et poss de donc un type En ce sens les programmes en Caml sont des valeurs 1 6 Impression Notion d effet Caml propose bien s r le moyen d imprimer des valeurs l cran ou dans des fichiers On utilise pour cela des fonctions dont le but n est pas d effectuer des calculs mais de produire des effets c est dire une action sur le monde ext rieur par exemple une interaction avec l utilisateur du programme l criture d un fichier ou d un message au terminal Un premier effet Nous allons r aliser un premier effet tr s simple nous crivons Bonjour l cran en utilisant la fonction pr d finie print_string qui a justement pour effet d imprimer son argument au terminal Une fonction pr d finie est une fonction qui 14 Premiers pas vous est fournie par le syst me Caml vous n avez donc pas besoin de l crire Ces fonctions sont d crites en d tails dans le Manuel de r f rence du langage Caml Elles sont aussi appel es fonctions primitives ou tout simplement primitives Essayons la primitive print_string print_string Bonjour Bonjour unit L impression s est produite comme pr vu Cependant Caml nous indique aussi que nous avons calcul un r sultat de type unit et qui vaut Le type unit est un type pr d fini qui ne contient
322. function Val_paire vi v2 gt codeur calcul d codeuri vi d codeur2 v2 _ gt raise Erreur paire attendue x L environnement initial let env_initial prim2 code_nombre prefix d code_nombre d code_nombre prim2 code_nombre prefix d code_nombre d code_nombre x prim2 code_nombre prefix d code_nombre d code_nombre prim2 code_nombre prefix d code_nombre d code_nombre prim2 code_bool en prefix d code_nombre d code_nombre lt gt prim2 code_bool en prefix lt gt d code_ nombre d code_nombre lt prim2 code_bool en prefix lt d code_nombre d code_nombre gt prim2 code_bool en prefix gt d code_nombre d code_nombre lt prim2 code_bool en prefix lt d code_nombre d code_nombre gt prim2 code_bool en prefix gt d code_nombre d code_nombre not primi code _bool en prefix not d code_bool en read_int prim code_nombre fun x gt read_int d code_nombre write_int primi code_nombre fun x gt print_int x print _newline 0 d code_nombrel L valuation d une phrase consiste calculer sa valeur et l afficher Si la phrase est une d finition il faut de plus enrichir l environnement global par la nouvelle liaison Fichier interprete ml let boucle let env_global ref env_initial in let flux_d entr e stream_of_channel std_in in while
323. function i gt print_int i print_char 1 2 3l 123 unit Ecrivons do_list let rec do_list f function El gt 0O x l1 gt f x do_list f l do_list a gt b gt a list gt unit lt fun gt Le raisonnement est le suivant si la liste argument est vide il n y a rien faire Sinon la liste argument est de la forme x 1 car elle n est pas vide En ce cas il faut valuer en s quence f x puis l action de f sur le reste de la liste qu on obtient par un appel r cursif do_list Remarquons que le type de la fonction do_list indique clairement que la fonction f doit accepter en argument les l ments de la liste puisque f a pour type a gt bet que la liste a pour type a list En revanche les r sultats des appels f sont ignor s f peut rendre un r sultat de n importe quel type Appliquer tous les l ments d une liste tant donn es une fonction f et une liste l la fonctionnelle map retourne la liste des r sultats obtenus en appliquant f chaque l ment de l Par exemple map successeur 1 2 3 retourne la liste 2 3 4 tandis que map carr 1 2 3 retourne 1 4 9 L expression map f ei e2 e retourne donc la liste f e1 f e2 f enl Graphiquement la fonction map distribue f sur les l ments de la liste argument l ta map f l 4 2 N KI N f o 5 NX e2 f e TON TON en fen Le nom map provient du langage
324. gistre int gt int value crire_registre int gt int gt unit value tableau_des_appels_syst me int gt int vect 262 Simulation d un processeur value ex cute instruction vect gt int gt unit L impl mentation de simul commence par une description Caml de l tat courant de la pico machine Cet tat se compose de l tat des registres de la m moire de code de la m moire de donn es et enfin de la valeur courante du pointeur de programme pc pour program counter qui contient l adresse de la prochaine instruction ex cuter Cet tat est donc d crit par un type enregistrement champs mutables contenant un tableau pour les registres le pointeur de code un tableau pour les instructions ex cuter et un tableau pour la m moire des donn es Fichier simul ml open code type tat_du_processeur registres int vect mutable pc int mutable code instruction vect mutable m moire int vect let pico registres make_vect nombre_de_registres 0 pc 0 code m moire La pico machine est cr e par la d finition de la variable pico Ses zones code et m moire des donn es sont provisoirement initialis es vides elles ne seront allou es qu au lancement de la machine en fonction de la taille du programme ex cuter et de la taille des donn es traiter Ex cution d une instruction Le simulateur fait voluer l t
325. gistres de la pile et de toutes les variables globales puis descend r cursivement dans les structures de donn es De ce parcours le GC d duit l ensemble des adresses m moire accessibles donc potentielle ment utilis es par le programme Toutes les autres adresses sont forc ment inutilis es et donc r cup rables Ce m canisme de parcours des donn es actives impose des contraintes sur la repr sentation des structures de donn es en m moire Essentiellement le GC doit savoir distinguer parmi les champs d une structure les pointeurs vers des sous structures qu il faut parcourir r cursivement des donn es qui ne sont pas des pointeurs comme par exemple les nombres entiers sur lesquels le GC doit arr ter son parcours L approche suivie par les syst mes Caml est de coder pointeurs et entiers de mani re les distinguer par examen de leur code Par exemple on code les adresses m moires par des mots pairs et les entiers par des mots impairs Le GC sait alors qu il doit parcourir r cursivement les mots pairs et ignorer les mots impairs Toutes les donn es non enti res sont repr sent es par l adresse m moire d un bloc de m moire allou bloc qui est muni d un en t te indiquant au GC la taille du bloc et le type de donn es contenues dans le bloc Les adresses sont naturellement des mots pairs sur la plupart des machines Quant aux entiers pour garantir qu ils sont toujours repr sent s par des mots im
326. gt lt gt flux and lire_expr6 flux lire_op ration lire_expr5 and flux and lire_expr flux lire_op ration lire_expr6 or flux Viennent ensuite des analyseurs pour les instructions les types les d clarations 282 Compilation de mini Pascal de variables les d clarations de fonctions les d clarations de proc dures et enfin les programmes Fichier syntaxe ml let rec lire_ instr flux match flux with lt MC if lire_expr ei MC then lire_instr i2 gt gt begin match flux with lt MC else lire_instr i3 gt gt If ei i2 i3 lt gt gt If ei i2 Bloc end lt MC while lire_expr e1 MC do lire_instr i2 gt gt While ei i2 lt MC write MC lire_expr e MC gt gt Write e lt MC read MC Ident nom MC gt gt Read nom lt MC begin lire_liste lire_instr il MC end gt gt Bloc il lt lire_expr e gt gt match e with Application nom el gt Appel nom el Variable nom gt begin match flux with lt MC lire _expr e gt gt Affectation_var nom e end Acc s_tableau ei e2 gt begin match flux with lt MC lire_expr e3 gt gt Affectation_tableau ei e2 e3 end _ gt raise Parse_error let rec lire_type function lt MC integer gt gt Integer lt MC boolean gt gt Boolean
327. gt printf add r 0 d r d n val_const cst reg Variable nom gt let var cherche_variable nom env in begin match var emplacement with Global_indirect n gt printf load r 0 d r 44 s n n reg nom Global_direct n gt printf add r 0 d r 44 s n n reg nom Local_indirect n gt printf load sp d r 44 s n profondeur_pile n reg nom Local_direct n gt printf add sp d r 44 s n Iprofondeur_pile n reg nom end Application fonc arguments gt let nbr_args list_length arguments in r serve_pile nbr_args let position ref O in do_list function arg gt compile_expr env arg 1 printf store sp d r 1 n Iposition position position taille du_mot arguments printf jmp F s ra n fonc lib re_pile nbr_args if reg lt gt 1 then printf add r 1 r 0 r d n reg Op_unaire op arg gt compile_expr env arg reg begin match op with gt printf sub r 0 r d r d n reg reg not gt printf seq r 0 r d r d n reg reg end Op_binaire op arg1 Constante cst2 gt compile_expr env argi reg printf s r d d r d n instr_pour_op op reg val_const cst2 reg Compilation 297 Op_binaire PAL lt gt and or as op Constante cst1 arg2 gt compile_expr env arg2 reg printf s r d d r d n instr_pour_op op reg val_const cst1 reg Op_binaire op argi arg2 gt let reg1 reg2
328. hier monfichier ml exactement comme le ferait l appel camle c monfichier ml du compilateur ind pendant La fonction compile accepte galement des fichiers d interface mli en plus des fichiers d impl mentation m1 La commande load_object monfichier zo charge en m moire le code compil qui se trouve dans le fichier monfichier zo et l ex cute phrase par phrase Les deux fonctions compile et load_object permettent donc de compiler et d ex cuter un programme crit sous forme modulaire partir du syst me interactif ce qui est pr cieux pour les utilisateurs de Macintosh ne dis posant pas du compilateur ind pendant Par exemple le programme logo se compile et s ex cute de la mani re suivante compile langage mli compile crayon mli compile langage ml compile alex mli compile asynt mli compile logo ml compile asynt ml compile crayon ml compile alex ml HHHH HHHH Compilations interactives 191 load_object crayon zo load_object langage zo load_object alex zo load_object asynt zo load_object logo zo M me lorsqu on dispose du compilateur ind pendant charger du code compil dans le syst me interactif avec la fonction load_object est souvent tr s utile pour essayer et mettre au point les fonctions d un programme Par exemple pour tester l analyseur syntaxique du mini Logo il suffit de lancer le syst me interactif et de faire
329. i bien qu la fin de la boucle l accumulateur contient le r sultat voulu on renvoie donc son contenu accu let fact n if n O then 1 else begin let accu ref 1 in for i 1 to n do accu i accu done laccu end fact int gt int lt fun gt 50 Programmation imp rative fact 10 int 3628800 Une petite remarque on peut supprimer le test if n 0 sans changer la s mantique de la fonction En effet lorsque n est nul la boucle s arr te instantan ment alors que la r f rence accu vaut 1 ce qui est le r sultat correct dans ce cas On obtient plus simplement let fact n let accu ref 1 in for i 1 to n do accu i laccu done laccu fact int gt int lt fun gt Cet exemple nous permet de comparer meilleur escient les styles imp ratif et fonc tionnel En effet nous avons d indiquer la machine la suite des op rations effectuer en g rant explicitement les modifications successives du contenu de l accumulateur accu il s agit vraiment ici d un programme de style imp ratif En revanche souvenez vous de notre pr c dente impl mentation r cursive de la fonction factorielle let rec factorielle function 0 gt 1 n gt n factorielle n 1 factorielle int gt int lt fun gt Dans ce cas on a presque l impression d avoir recopi la d finition math matique Vous comprenez ais ment que le style imp ratif est plus de
330. i maintenant la fonction qui compresse un fichier correspondant au descripteur de fichier entr e et crit le r sultat sur un autre fichier correspondant au descripteur de fichier sortie Fichier huffman ml type table_de_codage caract re int list vect mutable fin int list let encode entr e sortie codage esbit__initialise try while true do let c input_char entr e in do_list esbit__ crire_bit sortie codage caract re int_of_char c done with End_of_file gt x fin du fichier d entr e do_list esbit__ crire_bit sortie codage fin esbit__finir sortie 242 Compression de fichiers Le codage employ est repr sent par un enregistrement du type table_de_codage La partie caract re est un tableau de 256 codes un pour chaque octet La partie fin est le code signalant la fin du fichier compress Les codes sont repr sent s par des listes d entiers O ou 1 La lecture du fichier d entr e se fait avec la fonction input_char de la biblioth que standard Cette fonction renvoie le prochain caract re du canal d entr e pass en ar gument Elle d clenche l exception End_of_file lorsque la fin du fichier est atteinte La mani re habituelle de lire tous les caract res d un fichier est de faire input_char l int rieur d une boucle infinie while true do done L exception End_of_file de fin de fichier fait sortir de la boucle elle doit tre r cup r e par une construc
331. i pourrait avantageusement tre supprim e De mani re plus g n rale il vaudrait mieux calculer l avance le nombre d emplacements de pile n cessaires pour les temporaires et les allouer une fois pour toutes au d but de la fonction plut t que d incr menter et de d cr menter le pointeur de pile chaque fois qu on a besoin d un temporaire 15 4 Pour aller plus loin Le compilateur Pascal pr sent dans ce chapitre se pr te de nombreuses extensions Une premi re direction est d enrichir le langage pointeurs nombres flottants fonctions et proc dures locales En particulier les fonctions et proc dures locales posent des probl mes de compilation int ressants Lorsque le langage interdit aux fonctions locales d tre renvoy es en r sultats par d autres fonctions comme c est le cas en Pascal un cha nage des blocs d activation dans la pile suffit En revanche dans les langages fonctionnels comme Caml o les fonctions sont des valeurs de premi re classe une pile ne suffit plus pour repr senter les environnements d valuation des fonctions et il est n cessaire de mod liser les fonctions par des structures allou es dynamiquement les fermetures closures en anglais Nous reviendrons sur cette notion au chapitre 17 Une deuxi me direction est d am liorer la qualit du code produit par le compi lateur En particulier il faudrait essayer de stocker les variables locales autant que possible
332. iaison cache l ancienne Pour r sumer disons que les tables de hachage se comportent exactement comme des listes d association physiquement modifiables Poussant cette intuition on peut tr s bien faire une impl mentation correcte du module hashtb1l l aide de listes d association sans employer la technique du hachage type a b t a b list ref let new n ref let add t c d t c d t let find t c assoc c t La vraie impl mentation de hashtbl esquiss e dans la prochaine section est bien plus complexe elle utilise du hachage pour acc l rer consid rablement l op ration find Cependant son comportement est exactement le m me que celui de l impl mentation na ve donn e ci dessus Retenons donc qu une table de hachage se comporte comme une liste d association ceci pr s que les op rations de recherche sont beaucoup plus efficaces Nous utiliserons donc une table de hachage pour stocker l ensemble des mots cl s d un analyseur lexical La table associe aux mots cl s eux m mes des cha nes de caract res les lex mes correspondants Elle est donc du type string lex me hashtbl__t Pour d terminer si un mot trouv dans le flux d entr e est un mot cl ou un simple identificateur on interroge tout simplement la table des mots cl s avec hashtbl__find Fichier lexuniv ml let mc_ou_ident table_des_mots_cl s ident try hashtbl__find table_des_mots_cl s ident with
333. ichier et la d coupe en pi ces rectangulaires Les param tres nx et ny donnent le nombre de pi ces horizontalement et verticalement l aide des fonctions de manipulations d image fournies par le module imagephoto de CamlTk la fonction d coupe_image charge l image depuis le fichier et la d coupe en nx ny petites images rectangulaires La premi re de ces images est alors abandonn e pour laisser de la place au trou du jeu de taquin les autres sont renvoy es en r sultat et vont constituer les pi ces du taquin La fonction remplir_taquin ci dessous se charge de positionner les pi ces du taquin dans une toile rectangulaire c pass e en argument Elle associe ensuite l v nement clic souris dans les pi ces une fonction Caml qui permet de d placer les pi ces Nous cr ons un composant trou de type rectangle pour repr senter l emplacement restant libre sur le taquin Ses coordonn es sont conserv es dans les r f rences trou_x et trou_y La matrice tableau bidimensionnel taquin associe chaque coordonn e x y 200 Interfaces graphiques le composant repr sentant la pi ce qui se trouve cet endroit Nous la remplissons avec la liste de pi ces pass e en argument Comme il manque exactement une pi ce pour remplir tout le jeu la derni re case de la matrice reste gale trou Chaque image de la liste pi ces est transform e en l ment de toile et plac e sa position initiale par la fonction canva
334. ien d une garde que nous tudions bri vement dans le prochain paragraphe Une d finition acceptable de gal serait donc let gal function x y gt if x y then true else false gal a a gt bool lt fun gt Remarque comme nous l avons vu au paragraphe 2 1 l alternative du corps de gal est inutile on la remplace donc simplement par sa partie condition pour obtenir let gal x y x y gal a a gt bool lt fun gt Ce qui nous permet de constater que la fonction gal ne d finit pas la fonction d galit mais est en fait un synonyme de l op rateur plus pr cis ment gal est la version non curryf e de l op rateur Combiner filtrage et tests les gardes Vous remarquerez sans doute que le filtrage permet une programmation partic uli rement claire et autorise l criture compacte de multiples conditions Cependant le simple filtrage structurel et lin aire ne permet pas de m langer la s lection sur la forme de la valeur filtr e et les tests sur les valeurs effectives des composants du filtre C est pourquoi le filtrage de Caml propose une construction suppl mentaire les gardes pour effectuer des tests arbitraires pendant le filtrage La clause filtre when condition gt 122 Les structures de donn es o condition est une expression bool enne quelconque filtre les m mes valeurs que filtre mais elle n est s lectionn e que dans le
335. ier analyseur lexical que nous crirons par la suite nous le r utiliserons tel quel pour tous les langages dont nous aurons besoin L analyseur lexical universel se pr sente sous la forme d un module lexuniv dont voici l interface Fichier lexuniv mli type lex me MC of string Ident of string Entier of int value construire_analyseur string list gt char stream gt lex me stream On trouvera une impl mentation de ce module la fin de ce chapitre section 12 8 L analyseur syntaxique L analyse syntaxique des propositions ressemble beaucoup l analyse syntaxique des expressions dans le mini Logo La principale nouveaut est que nous allons prendre en compte les priorit s entre op rateurs Par exemple vous savez qu en arithm tique 1 2 x3 signifie 1 2 x 3 et que 1 x 2 3 veut dire 1 x 2 3 Les deux critures sont tol r es et ont la m me signification On dit que l op rateur x a une priorit plus lev e que l op rateur Cependant l analyseur syntaxique du mini Logo traduit 1 2 3 par Produit Constante 1 Somme Constante 2 Constante 3 ce qui correspond 1 x 2 3 En effet il analyse d abord 1 comme une expression puis voit l op rateur et se rappelle donc r cursivement pour lire l expression la droite du dont il fait le deuxi me argument du constructeur Produit L analyseur syntaxique du mini Logo ne tient donc pas compte des priorit s rel
336. if r ponse 0 then optioni else option menu string gt unit gt a gt string gt unit gt a gt a lt fun gt Um 68 Fonctionnelles et polymorphisme Pour nos essais nous d finissons deux petites proc dures qui impriment simplement un message au terminal let au_revoir print _ string Au revoir print _newline au_revoir unit gt unit lt fun gt let continuer print_string Continuons print_newline continuer unit gt unit lt fun gt Nous obtenons alors le dialogue suivant menu Arr ter au_revoir Continuer continuer lt 0 gt Arr ter lt 1 gt Continuer Choisissez votre option 1 Continuons unit Menu plusieurs cas Pour g n raliser la proc dure pr c dente un nombre quelconque d options il suffit de lui passer deux tableaux en arguments un tableau de cha nes de caract res pour les messages d invite et un tableau de proc dures pour les options Il faut maintenant crire le menu avec une boucle for parcourant le tableau des messages puis lire l option choisie par l utilisateur et s lectionner la proc dure correspondante du tableau des options let menu invites options for i 0 to vect_length invites 1 do print_string lt string_of_int i gt invites i done print_newline print_string Choisissez votre option let r ponse read_int in options r pons
337. ignes en fait 1441777 caract res ou environ 300 pages de ce livre Pour x4 nous vous laissons attendre le r sultat s il vous int resse Retenons qu il existe des programmes Caml de quelques lignes mettons trois qui demandent un temps de typage exorbitant Nous avons donc la preuve que cet algorithme est au moins exponentiel dans le pire des cas Sa complexit en moyenne est difficile estimer qu est ce qu un programme Caml moyen de taille n Nous sommes donc en pr sence d un algorithme ayant une complexit extr mement lev e dans le pire des cas mais une complexit lin aire en pratique c est dire pour les donn es qu on lui donne effectivement traiter Dans le pire des cas tout se passe comme si on parvenait soumettre l algorithme des donn es compl tement improbables sur lesquelles il pr sente une complexit maximale En pratique les programmes Caml qu on crit vraiment sont peu polymorphes et dans ce cas l algorithme de typage est effectivement lin aire Finalement le pire n est pas forc ment le plus probable heureusement Concept g n ral d unification Pour r soudre les quations de typage nous avons introduit la notion d unification Cette notion n est pas restreinte aux probl mes d quations entre types elle se d finit dans le cadre plus g n ral des alg bres de termes c est dire des structures math matiques minimales o l on puisse parler de variab
338. ilement que le tableau repr sentant p x q a pour longueur vect_length p vect_length q 1 Le programme Caml est bien plus court que ces explications 46 Programmation imp rative let multiplie _polyn mes_ pleins p q let produit make_vect vect_length p vect_length q 1 O in for i 0 to vect_length p 1 do for j 0 to vect_length q 1 do produit i j lt p i q j produit i j done done produit multiplie_polyn mes_pleins int vect gt int vect gt int vect lt fun gt Notre programme effectue sans peine le produit des polyn mes 1 2x 3x et 4 5x 6x que nous avions pr c demment calcul la main imprime_polyn me_ plein multiplie_polyn mes_pleins l1 2 31 l4 5 61 4 13x 28x 2 27x 3 18x 4 unit Comme exemple plus consistant calculons x 1 puis x 1 4 et x 1 let p 1 11 in let p2 multiplie_polyn mes_pleins p p in let p4 multiplie_polyn mes_pleins p2 p2 in let p8 multiplie_polyn mes_pleins p4 p4 in print_string x 1 2 imprime_polyn me_ plein p2 print _newline print_string x 1 x 4 imprime_polyn me_ plein p4 print _newline print_string x 1 x 8 imprime_polyn me_ plein p8 print_newline x 1 2 1 2x x 2 x 1 xx 4 1 4x 6x 2 4x 3 x 4 x 1 xx 8 1 8x 28x72 56x73 70x74 56x75 28x76 8x 7 x 8 unit 3 5 Cara
339. iliaire pour imprimer les mouvements puis la proc dure principale let mouvement de vers print_string D place un disque de la tige de la tige print _newline mouvement string gt string gt unit lt fun gt vers let rec hanoi d part milieu arriv e function 0 gt O n gt hanoi d part arriv e milieu n 1 mouvement d part arriv e hanoi milieu d part arriv e n 1 hanoi string gt string gt string gt int gt unit lt fun gt Les noms des arguments d part milieu et arriv e sont chang s lorsque nous voulons d placer les disques d une tige l autre par exemple pour d placer un disque de la tige de nom d part vers la tige argument milieu nous crivons hanoi d part arriv e milieu 1 hanoi wau R nc 3 D place un disque de la tige la tige C D place un disque de la tige la tige B D place un disque de la tige C la tige B D place un disque de la tige la tige C D place un disque de la tige B la tige D place un disque de la tige B la tige C D place un disque de la tige la tige C unit V rifiez le casse t te est r solu C est magique On n a pas vraiment l impression d avoir crit un programme si savant Ne vous inqui tez pas si vous prouvez des difficult s comprendre la proc dure hanoi C est normal car c est le premier exemple de programme Caml qui nous oblige
340. iment par exemple rempla ons 1 par print_int 1 1 On doit obligatoirement parenth ser une s quence pour l inclure dans une op ration Puis effectuons le calcul en commen ant par l une ou l autre de ses sous expressions d abord 1 2 puis 3 4 54 Programmation imp rative let un_fois deux print_int 1 1 x print_int 2 2 in let trois_fois_quatre print_int 3 3 print_int 4 4 in un_fois_deux trois_fois_quatre 2143 int 14 let trois_fois_ quatre print_int 3 3 print_int 4 4 in let un_fois_ deux print_int 1 1 print_int 2 2 in un_fois_deux trois_fois_quatre 4321 int 14 On n obtient videmment pas les m mes impressions l cran Laissons le compilateur nous d voiler l ordre qu il choisit print_int 1 1 x print_int 2 2 print_int 3 3 x print_int 4 4 4321 int 14 Un autre compilateur aurait pu choisir un autre ordre La conclusion de cette exp rience est qu il ne faut jamais m langer effets et appels de fonctions car on ne sait pas alors d terminer le moment o les effets vont intervenir En effet l ordre d valuation des ar guments d une fonction n est pas garanti par le langage Seules la s quence l alternative et la construction let ont un ordre d valuation d termin Ce n est pas tonnant pour la s quence puisque c est son r le de fixer l ordre d valuation de deux expressions Pour l alternative i
341. in est un puzzle invent en 1879 par Sam Lloyd et constitu de pi ces rectangulaires D une des pi ces manque ce qui permet de d placer les autres pi ces en les faisant glisser dans l espace ainsi m nag Le but du jeu est bien s r de reconstituer l image en faisant ainsi glisser les pi ces Ce petit jeu est l occasion d introduire un nouvel outil de placement des composants la toile canvas Jusqu ici tous nos placements de composants s effectuaient par la fonction pack qui empile les composants les uns sur les autres L utilisation d une toile permet de placer les com posants en donnant leurs coordonn es x y l int rieur de la toile C est particuli rement utile pour manipuler des composants de nature g om trique tels que polygones ovales ou images num ris es bitmaps Les coordonn es des composants dans la toile peuvent tre chang es tout instant ce qui permet de les d placer l cran let d coupe_image img nx ny let 1 imagephoto__width img and h imagephoto__height img in let tx 1 nx and ty h ny in let pi ces ref in for x 0 to nx 1 do for y 0 to ny 1 do let pi ce imagephoto__create Width Pixels tx Height Pixels ty in imagephoto__copy pi ce img ImgFrom x tx y ty x 1 tx y 1 ty pi ces pi ce lpi ces done done tx ty tl pi ces Nous commen ons par une fonction qui charge une image au format GIF depuis un f
342. incr mentalement chaque caract re d cod en suivant exactement le m me algorithme que le compresseur De la sorte l arbre de d codage et l arbre de codage voluent en phase Sur des fichiers assez longs l algorithme de Huffman dynamique atteint les m mes taux de compression que l algorithme de Huffman statique Pour atteindre des taux de compression plus lev s il faut passer une autre famille d algorithmes de compression dus Lempel et Ziv qui exploitent une autre source de redondance dans les fichiers de donn es outre le fait que certains caract res appa raissent plus fr quemment que d autres on trouve aussi des s quences de plusieurs caract res qui apparaissent plus fr quemment que d autres Par exemple dans un pro gramme Caml les mots cl s comme let ou function reviennent tr s souvent L id e des algorithmes de Lempel Ziv est d attribuer un code ces cha nes plus fr quentes que les autres et de les remplacer par leur code Cette id e se pr te de nombreuses variantes qui diff rent par la m thode de reconnaissance des cha nes fr quentes et par la mani re de les coder Les compresseurs les plus efficaces combinent ces algorithmes avec l algorithme de Huffman dynamique r injectant la sortie du premier dans l entr e du second pour tirer parti des deux types de redondance Bibliographie Des livres entiers ont t consacr s aux divers algorithmes de compression voir par exempl
343. ine ou caract re par caract re avec input_char et fermeture par close_in let canal_ entr e open_in essai tmp canal_entr e in_channel lt abstr gt input_char canal _entr e char U input_line canal _entr e string ne ligne de texte input_line canal _ entr e Exception non rattrap e End_of_file Comme on le voit sur le dernier exemple l exception End_of_file se d clenche lorsqu on essaye de lire apr s la fin du fichier La lecture au clavier et l affichage l cran sont en fait des cas particuliers d entr es sorties sur fichiers Le syst me fournit en effet trois canaux pr d finis Identificateur Nom savant Reli std_in entr e standard du programme clavier std_out sortie standard du programme cran std_err sortie d erreur du programme cran Programmes en plusieurs modules 183 Par exemple print_string s est exactement quivalent output_string std_out s et de m me read_line est synonyme de input _line std_in Une autre mani re de lire un fichier caract re par caract re est de passer par l interm diaire d un flux La fonction stream_of_channel renvoie le flux des caract res lus depuis un canal d entr e En particulier stream_of_channel std_in est le flux des caract res tap s au clavier C est cette fonction qui va nous permettre d appliquer des analyseurs lexicaux non plus des cha nes de caract res
344. infructueuses En effet pour trouver un objet dans une liste d association il faut en moyenne parcourir la moiti de la liste si l on suppose qu on recherche des cl s en moyenne dispos es au hasard dans la liste Pour constater que la cl est absente de la liste c est pire il faut parcourir toute la liste C est le cas le plus fr quent dans l exemple de l analyse lexicale Le seul moyen d acc l rer la recherche d une cl dans un ensemble est d liminer tr s rapidement un grand nombre de tests en prouvant tr s vite qu ils sont vou s l chec En particulier on ira beaucoup plus vite si l on est capable de restreindre la recherche exhaustive de la cl un ensemble beaucoup plus petit que celui de d part C est toujours le principe de diviser pour r gner qui pr vaut Le hachage consiste donc fractionner un gros ensemble de cl s en sous ensembles coh rents et ne chercher une cl que dans le petit sous ensemble qui la concerne La m thode suppose donc qu on dispose d un moyen tr s rapide de d terminer le sous ensemble auquel une cl est susceptible d appartenir Les sous ensembles sont par ex emple de simples listes on les regroupe en un tableau afin de pouvoir acc der di rectement n importe quel sous ensemble On repr sente donc le sous ensemble auquel appartient une cl par un simple num ro l indice du sous ensemble dans le tableau des sous ensembles La fonction qui d
345. int D clarations de fonctions d cl_fonc function f x int int Programmes programme program prog Ces types concrets sont d finis dans l interface du module syntaxe Fichier syntaxe mli type constante Enti re of int Bool enne of bool type expr_type Integer le type des entiers Boolean le type des bool ens Array of int int expr_type le type des tableaux x les deux int sont les bornes type expression Constante of constante Variable of string Application of string expression list Op unaire of string expression Op_ binaire of string expression expression Acc s_tableau of expression expression type instruction Affectation_var of string expression Syntaxe abstraite syntaxe concr te 279 Affectation_tableau of expression expression expression Appel of string expression list x appel de proc dure If of expression instruction instruction While of expression instruction Write of expression Read of string Bloc of instruction list x bloc begin end type d cl_proc proc_param tres string expr_type list proc_variables string expr_type list proc_corps instruction and d cl_fonc fonc_param tres string expr_type list fonc_type_r sultat expr_type fonc_variables string expr_type list fonc_corps instruction type programme prog_variables string expr_typ
346. ion 11 2 est traduit d un pro gramme de John Ousterhout I Programmer en Caml Avertissement O N IN A PREMI RE PARTIE de ce livre est une introduction progressive au langage gt Caml On n y suppose pas de connaissances pr alables autres que des no tions l mentaires de math matiques du niveau du lyc e Les exemples de pro grammes que nous vous pr sentons vont de l exemple d une ligne au vrai programme de plusieurs pages Tous les exemples ont t m rement r fl chis pour tre soit tonnants voire amusants pourquoi pas soit r ellement utiles ou repr sentatifs des programmes qu on crit vraiment Si bien que nous esp rons que tous pourront nous lire avec profit du d butant en programmation ignorant compl tement Caml et d sirant s en faire une id e l tudiant confirm qui trouvera mati re r flexion dans des programmes non triviaux En s adressant un si vaste public nous avons tent d acc l rer la lecture de tous le d butant verra souvent des sections qu on lui sugg re de ne pas lire car elles sont compliqu es et pas indispensables pour la suite tandis que le sp cialiste sera invit sauter des chapitres entiers si ses connaissances le lui permettent Par exemple le prochain chapitre d bute par un avertissement au sp cialiste Si vous savez d j que 2 2 font int 4 vous pouvez sauter ce chapitre En revanche le chapitre 3 contient une s
347. ion d impression comme print_string Les diff rences entre l utilisation interactive et la construction de programmes ind pendants sont faibles les deux modes effectuent presque les m mes op rations mais dans un ordre diff rent Voici ce qui se passe quand on charge un fichier inter activement avec include gauche compar avec ce qui se passe quand on compile ce fichier puis qu on l ex cute droite include fichier ml camlc o fichier fichier ml lecture de la phrase 1 lecture de la phrase 1 typage et compilation de la phrase 1 typage et compilation de la phrase 1 ex cution du code de la phrase 1 sauvegarde du code de la phrase 1 impression des r sultats lecture de la phrase 2 lecture de la phrase 2 typage et compilation de la phrase 2 typage et compilation de la phrase 2 sauvegarde du code de la phrase 2 ex cution du code de la phrase 2 impression des r sultats camlrun fichier ex cution du code de la phrase 1 ex cution du code de la phrase 2 10 3 Entr es sorties de base Reprenons nos tentatives de r alisation d un syst me Logo ind pendant de Caml Light Il ne suffit pas de compiler avec camlc le fichier logo ml contenant toutes les d finitions du type tat du chapitre 8 la fonction logo du chapitre 9 Ce fichier ne 182 Programmes ind pendants et modules contient que des d finitions de fonctions l ex cution du code compil va donc ex cuter les d finitions de foncti
348. ion lire_lex me qui prend un flux de caract res en argument reconna t le premier lex me au d but de ce flux et renvoie l objet de type lex me qui le d crit Comme la lecture sur les flux est destructrice lire_lex me aura retir du flux les caract res du lex me il suffira donc de rappeler lire_lex me sur le m me flux pour lire le lex me suivant La mani re la plus pratique de lire un flux n est pas d appeler stream_next mais de faire du filtrage sur les premiers l ments du flux Voici par exemple une fonction qui supprime tous les caract res blancs espaces tabulations et retours chariot en t te d un flux Analyse lexicale et syntaxique 163 let rec saute_blancs flux match flux with lt gt gt saute blancs flux est l espace lt f tf gt gt saute_blancs flux t est la tabulation K n gt gt saute_blancs flux n est la fin de ligne C lt gt gt O saute_blancs char stream gt unit lt fun gt Comme les expressions de flux les motifs sur les flux sont not s entre crochets pointus lt gt Ils filtrent le d but du flux et non pas le flux tout entier Ainsi le motif lt gt filtre n importe quel flux et non pas uniquement les flux vides comme on pourrait le croire De m me le motif lt m gt o m est un motif quelconque filtre tous les flux dont le premier l ment est filtr par m m m
349. iqu es sans obligation de sauvegarder leur contenu Une application de fonction a donc besoin de tous les reg istres Pour une op ration unaire comme not e si on peut valuer e avec n registres libres on peut aussi valuer not e avec n registres libres il suffit d valuer e dans un certain registre r puis de faire l instruction seq r 0 r r qui ne n cessite pas de registre temporaire suppl mentaire Le cas des op rations binaires est plus subtil Pour valuer e1 e2 par exemple on peut commencer par valuer e1 puis e2 puis faire add sur les deux r sultats Mais il faut que la valeur de e ne soit pas d truite pendant l valuation de e2 Pour ce faire on a besoin d un registre libre suppl mentaire pendant l valuation de e2 registre dans lequel on conservera la valeur de e1 Les besoins de l expression e1 e2 ainsi compil e sont donc le plus grand de besoins e et de 1 besoins e2 Si les expressions e1 et e2 sont susceptibles d interf rer nous sommes oblig s pour respecter la s mantique de mini Pascal d valuer e d abord puis e2 En revanche si l une des expressions est garantie sans interf rences nous pouvons valuer e2 avant e1 sans changer le comportement du programme Si on value d abord e2 puis e1 le nombre de registres utilis s est le plus grand de besoins ez et de 1 besoins e1 On choisit donc celle des deux strat gies qui utilise le moins de registres On montre facilement que la
350. ique d finit aussi un calcul sur les phrases math matiques ind pendant de leur signification r elle qui ne s attache qu la v rit des phrases On d duit ainsi la v rit d une phrase complexe par un simple calcul partir de la v rit de ses composantes 208 D monstration de propositions Par exemple sachant que P est vraie et que Q est fausse on saura calculer si le contraire de la phrase P ou Q est vrai ou faux Les propositions La premi re tape est donc de d finir ce qu on entend par phrase math matique En effet tout nonc n est pas forc ment une phrase math matique Le crit re minimal est la non contradiction une phrase math matique peut tre vraie ou fausse mais on exige qu elle ne soit pas la fois vraie et fausse Un exemple paradigmatique de phrase contradictoire est le paradoxe du menteur c est la simple phrase Je mens En effet cette phrase est la fois vraie et fausse On le d montre facilement en la supposant d abord vraie et en montrant qu elle est alors forc ment fausse puis en la supposant fausse et en montrant qu alors elle est vraie 1 Supposons la phrase vraie C est donc qu il est vrai que la personne qui parle ment qu elle ne dit pas la v rit Donc cette personne nonce des phrases fausses et donc la phrase qu elle vient d noncer Je mens est fausse 2 Supposons la phrase fausse La phrase Je mens est donc inexacte C est d
351. ire exception Mauvais_arguments if sys__interactive then else try if vect_length sys__command_line lt 2 then raise Mauvais_arguments let taille_m moire if vect_length sys__command_line lt 3 then 1024 else try int_of_string sys__command_line 2 with Failure _ gt raise Mauvais_arguments in ex cute_fichier sys__command_line 1 taille_du_mot taille_m moire exit 0 with Mauvais_arguments gt prerr_endline Usage pico_run lt fichier gt taille m moire exit 2 Fichier_incorrect gt prerr_endline Le fichier ne contient pas du code ex cutable exit 2 Erreur message param gt prerr_string Erreur l ex cution prerr_string message prerr_string prerr_int param prerr_endline exit 2 sys__Sys_error message gt prerr_string Erreur du syst me exit 2 prerr_endline message Le programme pico_run s obtient par une s rie d appels au compilateur ind pendant suivie d un appel l diteur de liens de Caml Light qui produit la commande elle m me camlc c code mli L assembleur 267 camlc c code ml camlc c simul mli camlc c simul ml camlc c exec ml camlc o pico_run code zo simul zo exec zo lt A A e a 14 3 L assembleur Nous passons maintenant au programme qui se charge de transformer un texte crit dans le langage du processeur en une suite d instructions directement compr hensibles par le processeur Ce progra
352. iserons la propri t pour tout n et m entiers positifs x r t Nous mod lisons les polyn mes l aide de tableaux d entiers le tableau des coef ficients de leurs mon mes Les degr s seront donc implicites simplement d termin s par l indice du coefficient dans le tableau qui repr sente le polyn me Par exemple le polyn me p x 2x 3 sera repr sent par le tableau contenant les nombres 3 2 1 dans cet ordre puisque 3 est le coefficient de degr 0 de p 2 est le coefficient de degr 1 et 1 le coefficient de degr 2 Nous tudions donc maintenant bri vement les tableaux de Caml Tableaux Les tableaux aussi appel s vecteurs sont des suites finies et modifiables de valeurs d un m me type Leur type est not la vect o a signifie n importe quel type Puisque les l ments des tableaux sont tous de la m me nature du m me type on qualifie les tableaux de suites homog nes de valeurs Les valeurs d un tableau sont enregistr es dans des cellules de m moire cons cutives Les positions des l ments dans un tableau d butent la position 0 Construction de tableaux Un tableau se d finit de deux fa ons soit en dressant directement la liste de ses l ments soit en cr ant le tableau et en remplissant ses cases ult rieurement Si un tableau est d fini par la liste de ses l ments cette liste est entour es des symboles et tandis que les l ments sont s p
353. iste est alors complet il n y a plus qu renvoyer son tat initial 16 6 R alisation de la commande grep Apr s cette envol e dans le monde des automates il est temps de revenir sur Terre et de finir l impl mentation de la commande grep La commande grep prend en arguments une expression rationnelle et une liste de noms de fichiers et affiche toutes les lignes des fichiers qui sont reconnues par l expression rationnelle Si aucun nom de fichier n est fourni grep lit son entr e standard C est ce comportement que nous allons maintenant programmer Les versions de grep qu on trouve dans les syst mes Unix proposent un certain nombre d options qui modifient le comportement de la commande inverser la recherche afficher uniquement les lignes qui ne sont pas reconnues identifier majuscules et minuscules afficher uniquement le nombre de lignes reconnues etc Ces options sont faciles mais fastidieuses impl menter nous les laisserons de c t Commen ons par deux fonctions qui appliquent un automate sur chaque ligne d un fichier et affichent les lignes reconnues Fichier grep ml open expr open auto open determ let ligne_trouv e ref false let grep_sur_canal auto nom_fich canal try while true do let ligne input_line canal in if reconna t auto ligne then begin ligne_trouv e true print_string nom_fich print _string print_endline ligne end done with End_of_file
354. it au hasard une r ponse parmi un ensemble de r ponses toutes faites pr par es par le programmeur L examen d une phrase consiste simplement chercher des mots connus du programme dans la phrase qui lui est soumise Les phrases sont class es sommairement en trois cat gories les phrases tr s simples par exemple r duites oui ou non pour lesquelles Cam lia dispose d un ensemble de r ponses types les questions phrases termin es par un caract re auxquelles Cam lia r pond C est moi qui pose les questions ou une phrase du m me genre et les phrases complexes pour lesquelles Cam lia cherche un mot int ressant comme famille ou p re ou sexe Si le programme trouve un mot int ressant il r agit par une phrase type toujours tir e au hasard parmi un ensemble pr par S il ne trouve pas de mot int ressant Cam lia n a rien dire d int ressant non plus elle se contente de relancer la conversation en imprimant par exemple Parlez moi un peu de vous Tout le sel de la conversation avec Cam lia vient de l utilisateur C est lui qui attache un sens pr cis aux phrases creuses de Cam lia L art du programmeur ne consiste ici qu faire dire au programme les phrases les plus creuses et les plus ambigu s possible pour laisser l utilisateur in terpr ter lui m me Pour impl menter Cam lia nous aurons besoin de fonctions nouvelles sur les listes et les cha nes de caract
355. it le programme Doctor qui existe encore sur de nombreux syst mes Unix Eliza tait capable d interpr ter les mots selon le contexte dans lequel ils apparaissaient et de tenir jour une repr sentation globale de ce qui s tait d j dit entre l ordinateur et l utilisateur Il pouvait ainsi apprendre des faits dans un domaine pr cis puis les utiliser ensuite bon escient Le principal apport d Eliza est sans doute d avoir montr qu une machine est capable de simuler un comportement raisonnablement intelligent lorsque le champ de la conversation est assez troit pour que le programmeur puisse cerner au pr alable les mots et les concepts qui vont intervenir et les introduire dans un programme 8 Graphisme Un petit dessin vaut mieux qu un long discours OUS ABORDONS maintenant le graphisme en Caml et illustrons l emploi des types enregistrement champs mutables Accessoirement nous r aliserons aussi de jolis dessins qu on obtient gr ce au graphisme tortue dans l esprit du langage de programmation Logo 8 1 Fractales Le but de ce chapitre notre chef d uvre graphique est de tracer une courbe fractale tr s connue le flocon de neige de von Koch Une courbe fractale est une courbe tr s tordue c est dire comportant beaucoup de plis G n ralement d finies r cursivement partir d un motif de base les fractales reproduisent l infini le motif chelle de plus en plus r duite
356. it un type pour une phrase en suivant des r gles de typage pour les constructions du langage comme la d finition et l application des fonctions De plus le type inf r contient le plus petit ensemble de contraintes n cessaires au bon d roulement de l ex cution du programme ici bon d roulement signifie qu il n y aura pas d erreurs de type l ex cution On dit que le contr leur de type trouve le type le plus g n ral de chaque expression notion introduite par Robin Milner en 1978 Par exemple la fonction successeur re oit le type int gt int parce que son argument doit tre un entier puisqu on lui ajoute 1 En revanche la fonction identit a le type a gt a parce qu il n y a pas de contrainte sur son argument Le polymorphisme s introduit donc naturellement partir de l absence de contraintes sur le type d un argument ou d une valeur Par exemple rappelons la d finition de la fonctionnelle double_le_r sultat_de let double _le_r sultat_de f int gt int function x gt double f x double_le_r sultat_de int gt int gt int gt int lt fun gt L argument f devait tre une fonction des entiers vers les entiers cause de la contrainte de type f int gt int explicitement crite dans le programme Mais si nous retirons cette contrainte de type nous obtenons une fonctionnelle plus g n rale let double_le_r sultat_de f function x gt double f x doub
357. iviale en informatique l analyse lexicale Lorsque l analyseur lexical a reconnu les mots de la phrase qu on appelle aussi lex mes ou unit s lexicales analyseur syntaxique regroupe ces mots en phrases selon les r gles de la grammaire la syntaxe concr te du langage reconna tre Prenons notre exemple favori avance 30 L analyseur lexical commence par re conna tre que la phrase est form e de deux mots avance et 30 Le lex me 30 est un entier car c est une suite ininterrompue de chiffres Notez que l analyseur lexical Analyse lexicale et syntaxique 161 ne se laissera pas d monter par une entr e un peu diff rente comme avance 30 deux espaces entre avance et 30 ou m me avance 30 qui s pare les deux mots par un saut de ligne et deux espaces Le travail de l analyseur syntaxique sera norm ment simplifi par cette normalisation de l entr e faite par la phase d analyse lexicale Dans notre cas l analyseur syntaxique examinera les r gles de la grammaire pour essayer de former une phrase avec les deux mots fournis par l analyseur lexical L une de ces r gles est justement lt Mot avance nombre n gt gt Av n qui signifie si l on rencontre le mot Mot avance suivi d un nombre n nombre n alors c est une phrase l gale gt dont la syntaxe abstraite est Av n L analyseur syn taxique nous renverra donc automatiquement la valeur Caml Av n que nous ne
358. l Lecture m moire Ecriture m moire Branchement Branchement si z ro Branchement si pas z ro Appel syst me Arr t de la machine ra re oit r 0 Ta re oit r o Ta re oit r o ra re oit r1 0 ra re oit r et o r2 re oit r ou o r2 re oit r ou exclusif o ra re oit r d cal gauche de o bits T2 re oit r d cal droite de o bits ro re oit 1 si r lt o 0 simon ro re oit 1 si r lt o 0 sinon ro re oit 1 si r 0 0 sinon r2 re oit le contenu de l adresse r o le contenu de r est crit l adresse r o saute l adresse o et stocke l adresse de l instruction suivant le jmp dans r saute l adresse a si r 0 saute l adresse a si r 0 n est le num ro de l appel fin du programme Figure 14 2 Le jeu d instructions de la pico machine 257 simple et uniforme le premier argument est un registre le deuxi me argument est soit un registre soit une constante et le r sultat est mis dans un registre Les op rations n acc dent jamais directement la m moire Les transferts de donn es entre registres et m moire de donn es sont assur s par les instructions load et store L adresse du mot m moire acc d est toujours de la forme r o o r est le contenu d un registre et o soit le contenu d un registre soit une constante En d autres termes le pico processeur n a que deux modes d adressage ind
359. l on renvoie 0 par la phrase try t te with Failure t te gt O int 0 Les exceptions 127 On crira donc la proc dure d incr mentation du compteur let ajoute_au_compteur compteur 1 compteur compteur try t te 1 with Failure t te gt O ajoute_au_compteur int ref gt int list gt unit lt fun gt let c ref O c int ref ref 0 ajoute_au_compteur c 1 c int 1 ajoute _au_compteur c c int 1 C est la m thode l mentaire d utilisation des exceptions de Caml Nous d crivons maintenant le m canisme dans toute sa g n ralit Valeurs exceptionnelles Le trait distinctif du traitement d erreurs en Caml et ce qui en fait la g n ralit est le statut des erreurs ce sont des valeurs part enti re du langage Elles appartiennent un type pr d fini exn et on les appelle valeurs exceptionnelles On les manipule donc comme toutes les autres valeurs Par exemple l chec signal par la fonction t te est la valeur exceptionnelle Failure t te let chec _de_t te Failure t te chec_de_t te exn Failure t te Remarquez que Failure n est rien d autre qu un constructeur de valeurs du type exn La propri t caract ristique des valeurs exceptionnelles est videmment qu on peut les d clencher on dit aussi les lever par analogie avec la locution lever une perdrix Pour lever une valeur exceptionn
360. l est clair qu on ne peut d cider la branche choisir qu apr s avoir valu la condition En ce qui concerne le let on value toujours l expression d finissante d abord dans let x e1 in e2 on value e avant e2 garantissant ainsi que la valeur de l identificateur est connue pendant le calcul de l expression e2 Effets et r gle n La r gle n du paragraphe pr c dent stipule que l expression function x gt f x est quivalente f Nous avons pr cis que cette r gle s applique quand f est une fonction En fait cette r gle s tend facilement au cas o f est une expression quelconque mais seulement dans le cas o cette expression f ne produit pas d effets Insistons la r gle est parfaitement correcte pour toute fonction f que f produise des effets ou non De plus cette r gle s tend toute expression pourvu que cette expression ne produise aucun effet Il est pourtant impossible d tendre la r gle une expression quelconque car certaines expressions produisant des effets l invalident Il est si tentant d utiliser cette r gle tendue sans v rifier que l expression impartie est sans effets que nous pensons n cessaire d tudier un exemple o les effets emp chent de l utiliser sous peine d erreur D finissons une fonction f qui incr mente son argument puis retourne une fonction en r sultat let f x incr x function z gt z 1 f int ref gt int gt int lt fun gt
361. le openTk in let img imagephoto__create File nom_ fichier in let c canvas__create fen tre _ principale Width Pixels imagephoto__width img Height Pixels imagephoto__height img in let tx ty pi ces d coupe_image img nx ny in remplir_taquin c nx ny tx ty permutation pi ces pack c mainLoop 11 5 Pour aller plus loin CamlTk est une biblioth que d une grande richesse et la pr sentation que nous en avons faite dans ce chapitre est forc ment incompl te Nous esp rons cependant qu elle aura convaincu le lecteur de la facilit avec laquelle on peut doter une application Caml d une interface homme machine de bonne facture Pour une pr sentation plus compl te de la bo te outils Tk on se reportera l ouvrage de John Ousterhout Tcl and the Tk toolkit Addison Wesley ou celui de Matt Welch Practical programming in Tcl and Tk Prentice Hall Il Exemples complets Avertissement Enfin de vrais programmes Pourquoi vrais Les programmes pr c dents taient ils faux ANS LA PREMI RE PARTIE de ce livre nous avons abord tous les m canismes essentiels du langage Caml Dans cette deuxi me partie nous d veloppons des exemples de programmes complets dans le but de montrer comment ap pliquer toute la puissance du langage la r solution de probl mes de programmation Nos programmes sont de vrais programmes ils sont issus de probl mes ayant une r elle importance pra
362. le 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 e au d but de chaque it ration Si elle est initialement fausse les actions ne sont jamais ex cut es Dans certains cas la boucle tant que sert r p ter ind finiment les m mes actions jusqu un v nement exceptionnel Dans ce cas la condition de boucle est tout simplement le bool en true comme dans while true do actions done Boucle pour Boucle pour for ident expression for pour to downto expression to jusqu down en bas do expression done do faire done fait La s mantique c est dire la signification de l expression for i d but to fin do actions done est de faire les actions avec i d but puis avec i d but 1 et ainsi de suite jusqu i fin En particulier si d but gt fin on n value jamais actions Pour la version downto on d cr mente l indice de boucle i on lui soustrait 1 chaque tour au lieu de l incr menter lui ajouter 1 L indice de boucle est forc ment du type entier Le nom associ 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 l aide
363. le connecteur non si P est une proposition alors non P est une proposition qui est fausse si P est vraie et qui est vraie si P est fausse Techniquement la proposition non P est souvent not e P ou encore P Pour ne pas multiplier les notations nous n utiliserons pas les noms techniques des connecteurs mais leur nom vulgaire Ainsi nous continuerons noter non le connecteur On d finit formellement le connecteur non en envisageant toutes les valeurs de v rit possibles de son argument La logique math matique 209 et en donnant pour chacune d elles la valeur de v rit correspondante de non P On crit donc cette d finition sous la forme d un tableau de cas qu on nomme table de v rit P non P v j f v Cette table comprend sur chaque colonne une proposition et ses diff rentes valeurs de v rit possibles La premi re ligne dresse ainsi la liste de toutes les propositions d crites par la table Les autres lignes donnent les valeurs de v rit de toutes les propo sitions de fa on coh rente c est dire selon les valeurs prises par les propositions de base La table pr c dente comprend donc deux lignes puisqu il y a deux cas possibles pour P La deuxi me ligne indique donc que lorsque P vaut v non P vaut f et la troisi me ligne que non P vaut v quand P vaut f Nous d finissons maintenant des op rations binaires le et la conjonction et le ou la disjonction
364. le est not e par un point d exclamation plac apr s son argument On a par exemple 4 4 x 3 x 2 x 1 La fonction factorielle est d finie par za 1 sin 0 nx n 1 sinon Cette d finition est r cursive le nom intervient dans le corps de sa propre d finition Donc pour comprendre la signification de n il faut comprendre celle de n 1 Cela semble difficile car on exige la compr hension d une notion qu on est justement en train d expliquer En fait cela se justifie parce que le calcul de n termine toujours il suffit d tre patient et de continuer le calcul jusqu atteindre 0 ce qui arrivera forc ment puisqu on explique la signification de n en fonction de n 1 Par exemple 3 3x 3 1 3x2 3x2x 2 1 3x2x 1 3x2x1x 1 1 3x2x1x0 3X2X1XxX1 6 La d finition math matique r cursive de la fonction factorielle est donc bien fond e on obtient finalement un r sultat pour tout argument entier naturel Ce genre de d finition se traduit tr s facilement en Caml mais pour cela nous devons explicitement pr venir Caml que nous d sirons faire une d finition r cursive gr ce une nouvelle construction let rec Avant de l employer expliquons pourquoi il est n cessaire d introduire une nouvelle construction Port e statique et d finitions r cursives En math matiques vous ne pouvez parler d une entit math matique avant d en avoir donn la d finitio
365. le nom d appel de la commande les l ments suivants les arguments de la commande Fichier compr ml if sys__interactive then else begin let erreur ref false in if vect_length command_line gt 2 amp command_line 1 d then for i 2 to vect_length command_line 1 do try d compresse_fichier command_line i with Erreur gt erreur true done else for i 1 to vect_length command_line 1 do try compresse_ fichier command_line i with Erreur gt erreur true done exit if lerreur then 2 else 0 end Les deux boucles r cup rent l exception Erreur pour passer au prochain argument de la ligne de commande en cas d erreur On positionne cependant le drapeau erreur pour pouvoir renvoyer au syst me d exploitation un code d erreur appropri le code z ro si aucune erreur ne s est produite un code non nul sinon Il est maintenant temps de passer aux choses s rieuses l impl mentation des algo rithmes de compression et de d compression 13 3 L algorithme de Huffman L algorithme de compression de Huffman repose sur l observation que certains car act res apparaissent plus fr quemment que d autres dans les fichiers Par exemple dans un fichier de texte e appara t plus souvent que z et l espace appara t plus souvent que le caract re tilde Au lieu de coder chaque caract re sur huit bits quelle que soit L algorithme de Huffman 241 sa fr quence nous allons at
366. le_le_r sultat_de a gt int gt a gt int lt fun gt La fonctionnelle devient polymorphe car le contr leur de type a d couvert que f devait seulement renvoyer un entier en r sultat mais qu il n est nullement obligatoire qu elle prenne un entier en argument Voici un exemple o f re oit une cha ne de caract res let double_de_la_longueur double_le_r sultat_de string_length double_de_la_longueur string gt int lt fun gt double_de_la_longueur Caml int 8 Le polymorphisme d coule donc de l absence de contraintes sur une valeur Cela explique pourquoi un param tre de type peut tre remplac sans risque d erreurs par n importe quel type y compris un type lui m me polymorphe Par exemple on applique la fonction identit elle m me en l employant avec le type Ca gt a gt Ca gt a let id x identit identit x id a gt a lt fun gt Puisque la fonction identit renvoie toujours son argument identit identit s value en identit et la fonction id est donc tout simplement gale la fonction identit L alg bre des types de Caml Nous allons maintenant pr ciser davantage l ensemble des types qu utilise le syst me Caml ce qu on nomme techniquement son alg bre des types Tout type Caml entre dans l une des cat gories suivantes Typage et polymorphisme 63 e Types de base comme int ou string e Types composites comme in
367. lection consistant d placer t j en t i o j est l indice tel que t j est le plus petit des l ments t i i 1 Ha t j est le minimum partir de i d finitivement en place a OEY 1 1 1 t 0 i 1 i j vect_length t 1 Pour traduire cet algorithme en Caml nous avons besoin d une proc dure auxil iaire qui se charge d changer deux l ments dans un tableau Il est bien connu que cette t che pr sente une petite difficult il faut garder une copie d un des l ments puisqu on perd cet l ment quand on crit l autre sa place Cela m rite bien une proc dure ind pendante de la fonction de tri La proc dure d change est naturelle ment polymorphe elle peut s appliquer tout type de tableau puisqu elle effectue une op ration ind pendante de la nature des l ments du tableau let change t i j change les l ments i et j de t let l ment_i t i in t G lt t G 66 Fonctionnelles et polymorphisme t j lt l ment_i change a vect gt int gt int gt unit lt fun gt Il n y a plus de difficult crire en Caml le tri par s lection let tri t for i 0 to vect_length t 2 do let min ref i in for j i 1 to vect_length t 1 do if t j lt t min then min j done change t i min done tri a vect gt unit lt fun gt
368. les de constantes et de fonctions d arit fix e C est aussi le m canisme d valuation de base des langages de programmation logique tels que Prolog Pour aller plus loin 363 Typage des valeurs mutables Nous n avons pas abord le typage des traits imp ratifs de Caml Si la compila tion des valeurs mutables et de l affectation n est pas un probl me difficile leur typage polymorphe est un probl me qui a fait couler beaucoup d encre La difficult vient essen tiellement du polymorphisme et de la g n ralisation des valeurs dont on peut changer dynamiquement le type par affectation en invalidant ainsi les hypoth ses du contr leur de type Prenons comme exemple le cas des r f rences Le type naturel de ref est Pour tout type la la la ref celui de l affectation est Pour tout type la la ref la unit et enfin le d r f rencement a pour type Pour tout type la la ref a Remarquez que ces types sont polymorphes Consid rez le programme suivant let y ref in y true y y 1 ly 1Y Entr e interactive gt Fe dise dy S PE Cette expression est de type bool list mais est utilis e avec le type int list Le contr leur de type a tr s soigneusement vit de g n raliser le type de la variable y d faut il aurait obtenu le type Pour tout type a a list ref En ce cas la premi re affectation aurait ins r true dans la liste point e par y et la seconde aur
369. les inconnues introduites pendant le typage de la derni re d finition La fonction g n ralisation en construit la liste en faisant bien attention ne pas mettre plusieurs fois la m me variable dans la liste cette liste constitue la liste des param tres du sch ma de type renvoy par g n ralisation Fichier types ml let g n ralisation ty let params ref in let rec trouve_param tres ty match valeur_de ty with Variable var gt if var niveau gt lniveau_de_liaison amp amp not memq var params then params var params Terme constr arguments gt do_vect trouve_param tres arguments in trouve_param tres ty param tres params corps ty Impression des types 397 let sch ma_trivial ty param tres corps ty L op ration de sp cialisation consiste associer une nouvelle inconnue chaque param tre du sch ma puis faire une copie du corps du sch ma en rempla ant les variables qui sont des param tres par l inconnue qui leur est associ e La recherche de l inconnue associ e un param tre de type donn a lieu dans la liste d association nouvelles_inconnues l aide de la fonction pr d finie assq similaire assoc mais utilisant le test d galit physique au lieu du test d galit structurelle Fichier types ml let sp cialisation sch ma match sch ma param tres with gt sch ma corps params gt let nouvelles_inc
370. leur de type nombre Cette fonction va donc envisager deux cas si le flux de lex mes commence par un lex me Constante_enti re i alors elle fabrique le nombre Entier i si le flux de lex mes commence par un lex me Constante_flottante f alors la fonction renvoie le nom bre Flottant f Tous les autres lex mes produiront une erreur se traduisant par le d clenchement de l exception pr d finie Parse_failure let nombre function lt Constante _enti re i gt gt Entier i lt Constante_flottante f gt gt Flottant f nombre lex me stream gt nombre lt fun gt Par exemple let flux_lex mes analyseur_lexical stream_of_string 123 1 05 fini flux_lex mes lex me stream lt abstr gt nombre flux_lex mes nombre Entier 123 nombre flux_lex mes nombre Flottant 1 05 Analyse lexicale et syntaxique 167 nombre flux_lex mes Exception non rattrap e Parse_failure La fonction qui analyse les ordres n est gu re plus compliqu e Pour les ordres sans argument elle se contente de chercher le mot correspondant comme premier lex me du flux Ainsi pour analyser l ordre baisse_crayon on aura la clause lt Mot baisse_crayon gt gt Bc Pour les ordres avec argument num rique on commence par d tecter l ordre puis on appelle l analyseur des nombres la fonction nombre pr c dente Cet appel a lieu encore une fois dans la partie filtre de la clau
371. lie donc par deux le nombre de param tres de type du r sultat let x0 in x0 x0 a list b list O let x0 in let x1 x0 x0 in x1 x1 a list b list c list d list O O 0O DO Pla ons nous directement au niveau 3 et arr tons nous l parce que les types grossissent trop vite let x0 in let x1 x0 x0 in let x2 x1 x1 in let x3 x2 x2 in x3 x3 Ca list b list x c list d list Ce list f list x g list h list Ci list J list k list l list Cm list n list x o list p list 0 0 0 0 C0 0 0 0 0 0 0 0 C0 0 0 0 On montre facilement qu au niveau 10 on aura 2 soit 1024 param tres de type et que le type du r sultat occupera presque 28000 caract res 15 crans de 24 lignes sur 80 colonnes Dans ce cas le typage du programme est bien plus long que son ex cution lex cution est instantan e puisqu il suffit de construire 10 cellules de paires La paire le constructeur infixe n est pas responsable de ce ph nom ne il est possible de le reproduire en n utilisant que des fonctions Il existe en effet un codage fonctionnel de la paire l id e consiste consid rer une paire comme un objet qui r pond aux messages premi re composante et seconde composante c est donc une fonction qui applique une projection ses deux composantes cha
372. lindrome string gt bool lt fun gt palindrome eluparcettecrapule bool true On simplifie encore un peu ce programme en crivant la palin l int rieur de palindrome ce qui lui te l argument s qui est li par la fonction palindrome et qui est donc visible par la fonction locale palin C est la version la plus jolie Par coquetterie nous avons aussi supprim les parenth ses autour des tests car elles sont implicites let palindrome s let rec palin i j i gt j s i s j amp amp palin i 1 j 1 in palin O string_length s 1 palindrome string gt bool lt fun gt palindrome tulaStroP cras C sarc PortSalut bool true 2 2 D finitions par cas le filtrage Nous avons donn la d finition r cursive suivante de la fonction factorielle let rec factorielle n if n 0 then 1 else n factorielle n 1 Caml dispose d une mani re encore plus concise de d finir cette fonction l analyse de cas Il y a ici deux cas possibles pour l argument de factorielle ou bien c est 0 ou bien il est diff rent de 0 On l crit ainsi let rec factorielle function 0 gt 1 n gt n factorielle n 1 factorielle int gt int lt fun gt 28 R cursivit L analyse de cas O gt 1 n gt n factorielle n 1 signifie simplement si l argument de la fonction est O alors renvoyer 1 sinon nommer n l argument de la foncti
373. lisateur entre une deuxi me phrase et ainsi de suite C est tr s pratique pour apprendre le langage et exp rimenter avec des fonctions mais malcommode pour construire de v ritables programmes Dans ce chapitre nous allons voir d autres modes d utilisation de Caml qui vitent d entrer sans cesse les m mes d finitions qui autorisent la constructions de programmes ind pendants utilisables sans connaissance pr alable de Caml et enfin qui procurent un moyen de structurer des gros programmes en modules 10 1 Chargement de fichiers Si vous avez eu la patience de taper un des gros exemples des chapitres pr c dents vous vous tes certainement demand comment sauvegarder tout ce travail afin de pouvoir r utiliser ult rieurement les fonctions que vous avez p niblement entr es Mal heureusement pour vous c est impossible dans le syst me Caml Light En revanche vous auriez pu crire les exemples sous un diteur de textes enregistrer le texte des pro grammes dans un fichier puis charger ce fichier dans le syst me interactif Caml Light fournit pour ce faire la fonction include appliqu e un nom de fichier include se charge de lire les phrases Caml contenues dans le fichier et de les ex cuter tout comme si vous les aviez tap es la main Par exemple supposons qu on ait mis dans le fichier facto ml les lignes suivantes let rec fact n if n lt 1 then 1 else n fact n 1 fact 10 On lance alors le
374. list a gt b gt a list gt unit lt fun gt do_list print_int 1 2 3l 321 unit La fonction est bien appliqu e sur tous les l ments de la liste mais l envers Les effets se produisent donc dans l ordre inverse de la vraie fonction do_list Cependant il suffit d exprimer do_list en fonction de it_list pour que tout rentre dans l ordre let do_list f 1 it_list function y gt function x gt f x y O l do_list a gt b gt a list gt unit lt fun gt do_list print_int 1 2 3l 123 unit Tentons alors d exprimer galement map en fonction de it_list let map f 1 it_list function res gt function x gt f x res 1l map a gt b gt a list gt b list lt fun gt Malheureusement la liste r sultat n est pas dans le bon ordre map successeur 1 2 3 int list 4 3 2 map function x gt print _int x successeur x 1 2 3 123 int list 4 3 2 En effet it_list accumule les r sultats dans la liste res en les ajoutant en t te de liste Comme dans le cas de rev on obtient ainsi la liste des r sultats l envers D ailleurs si l on ne fait qu accumuler les l ments sur la liste des r sultats pr c dents on obtient effectivement une autre version de rev let rev 1 it_list function res gt function x gt x res l rev a list gt a list lt fun gt re
375. llant sur des valeurs de type polyn me fera typiquement une dis crimination sur les valeurs du type par un filtrage du genre let f function Plein v gt Creux 1 gt Remarquez que le filtrage permet la fois de d terminer le type du polyn me et de r cup rer son tableau ou sa liste de mon mes C est strictement analogue au cas des listes o nous crivions let f function O gt x reste gt C est maintenant un jeu d enfant que d crire la fonction d impression des valeurs de type polyn me let imprime_polyn me function Plein v gt imprime _ polyn me plein v Creux 1 gt imprime_polyn me_ creux l imprime_polyn me polyn me gt unit lt fun gt imprime_polyn me pl 1 2x 3x 2 unit imprime_polyn me p2 1 x 100 unit Op rations sur les valeurs de type polyn me Nous d finissons l addition et la multiplication des polyn mes creux ou pleins Puisque les polyn mes se pr sentent sous deux formes nous avons quatre cas en visager L id e est simple e la somme de deux polyn mes creux est un polyn me creux on appelle l addition des polyn mes creux e la somme de deux polyn mes pleins est un polyn me plein on appelle l addition des polyn mes pleins e la somme de deux polyn mes d esp ces diff rentes est un polyn me creux En effet si l un des polyn mes est creux il comprend beaucoup de z
376. lle ANS CE CHAPITRE nous programmerons une commande de compression de fichiers La compression consiste transformer des fichiers pour qu ils occu pent moins de place l op ration inverse la d compression reconstruit les fichiers de d part partir des fichiers transform s Ce sera l occasion d introduire quelques algorithmes classiques en particulier deux exemples int ressants d utilisation des arbres binaires parmi bien d autres Nous aurons galement besoin de faire des entr es sorties bit par bit et donc de manipuler les entiers au niveau du bit 13 1 La compression de donn es La plupart des fichiers stock s dans les ordinateurs contiennent un certain degr de redondance Tr s souvent si l on code diff remment les donn es qu ils contien nent on r duit consid rablement leur taille sans perte d information si l on suppose videmment que le processus de recodage est r versible et qu il permet donc de retrou ver les fichiers d origine tout instant C est ce recodage qu on appelle compression des donn es Les proc d s de compression et de d compression de donn es sont de plus en plus employ s dans les environnements informatiques en premier lieu dans des programmes utilitaires sp cialis s comme gzip stuffit ou pkzip qui souvent combinent compres sion et archivage regroupement d une hi rarchie de fichiers en un seul fichier mais aussi dans certains pilotes de di
377. lle_du_mot Les fonctions r serve_pile et lib re_pile mettent du code machine qui modifie le registre pointeur de pile et modifient profondeur_pile pour que le code mis pour les acc s aux variables relativement ce registre reste correct Le code est mis sur la sortie standard l aide de la fonction printf du module de biblioth que printf Tout comme la fonction sprintf que nous avons rencontr e dans la section 11 2 printf prend en argument une cha ne de format et un certain nombre d entiers ou de cha nes de caract res et remplace dans le format les s quences de la forme plus une lettre par le prochain argument Au contraire de sprintf qui renvoie le r sultat du formatage sous forme de cha ne printf l affiche directement sur la sortie standard Par exemple printf add r d s r d 1 tiquette 2 affiche add r 1 tiquette r 2 La lettre suivant indique le type de l argument afficher et le format d affichage utiliser Parmi les nombreux formats existants nous n en utiliserons que deux d qui affiche un entier en d cimal et s qui affiche une cha ne de caract res Fonctions d analyse des expressions Nous passons maintenant des fonctions auxiliaires qui calculent certaines pro pri t s des expressions La premi re calcule le type d une expression de tableau c est dire les bornes inf rieures et sup rieures du tableau ainsi que le type des l ments cette derni
378. logique math matique l mentaire De surcro t nous compl terons nos connaissances sur l analyse syntaxique et lexicale en introduisant un g n rateur d analyseurs lexi caux et les concepts de mot cl r serv et de priorit des op rateurs Pour expliquer le g n rateur d analyseurs lexicaux nous serons aussi oblig s d introduire les tables de hachage une structure de donn es tr s utile 12 1 La logique math matique La logique math matique traite de la v racit des phrases math matiques et de la validit des raisonnements Elle permet de r pondre des questions comme sachant que la phrase P est vraie et que la phrase Q est fausse est ce que la phrase obtenue en disant P et Q est une phrase vraie Un exemple plus complexe le raisonnement suivant est il correct Puisque P est vraie et que Q est fausse P n est donc pas une condition n cessaire pour que Q soit vraie R ponse la section 12 7 La logique math matique permet de r pondre ces ques tions en d finissant pr cis ment les op rations autoris es sur les phrases math matiques et la signification de ces op rations Une op ration licite est par exemple de relier deux phrases math matiques par et comme dans 2 est pair et 2 est un nombre pre mier La logique math matique fournit donc un sens pr cis tous les petits mots qu on emploie dans les raisonnements comme donc or car et ou etc La log
379. ls droit On impose la condition suivante La priorit d un n ud est inf rieure ou gale la priorit de tous les n uds contenus dans ses fils gauche et droit Ainsi les priorit s vont en croissant quand on se d place de la racine vers une feuille Voici un exemple d arbre binaire croissant Comme dans le cas de l impl mentation par des listes ordonn es l l ment de la file ayant la plus faible priorit est facile trouver c est toujours l l ment la racine de l arbre Pour impl menter extraire il reste donc savoir combiner les deux fils de la racine en un seul arbre binaire croissant qui repr sente la file de d part priv e de son l ment le moins prioritaire La racine du nouvel arbre est l l ment de plus petite priorit parmi ceux qui restent Ce ne peut tre que le sommet du fils gauche ou le sommet du fils droit puisque tous les autres n uds sont moins prioritaires On d place donc celui des deux sommets qui a la plus petite priorit pour le mettre la racine FE LA Bien entendu il y a maintenant un trou dans l un des deux fils trou qu il faut son tour combler en r p tant le m me raisonnement Annexes 249 6 fa La proc dure s arr te lorsqu elle atteint une feuille de l arbre Le r sultat est bien un arbre binaire croissant contenant les m mes l ments que celui de d part moins la racine Fichier fileprio ml let rec enl ve_sommet
380. lt 0 try while true do cycle_d horloge done with Arr t gt Les appels syst me Il nous reste mettre en place un pico syst me d exploitation savoir les ap pels syst me pour la lecture et l criture d un nombre Nous d finissons donc les deux fonctions correspondantes et les rangeons dans le tableau des appels syst me Fichier simul ml let appel_syst me_read _ try read_int with Failure _ gt raise Erreur erreur de lecture 1 and appel _syst me_write argument print_int argument print _newline O argument tableau_des_appels_syst me 0 lt appel_syst me_read tableau_des_appels_syst me 1 lt appel_syst me_write Dans un vrai processeur les appels syst me sont bien s r crits en assembleur et acc dent directement aux ressources mat rielles de la machine Par exemple la primi tive d impression irait plus ou moins directement crire dans la m moire d cran de la machine chacun des chiffres du nombre tandis que la routine de lecture d un nombre interrogerait le clavier et transformerait les codes des touches frapp es en un nombre entier l aide d une boucle similaire celles utilis es dans nos analyseurs syntaxiques Pour simplifier c est Caml qui nous permet cet acc s direct aux ressources de la ma chine ce qui nous vite de d crire la connexion du processeur avec ses p riph riques Le programme principal Pour lancer l
381. lt fun gt Et maintenant t te nous signale une erreur dans la fonction t te t te Exception non rattrap e Failure t te Ce m canisme de d clenchement d erreurs est utile mais il se peut que nous voulions r cup rer ces erreurs parce que nous savons comment continuer les calculs apr s une telle erreur qui devient une erreur attendue du point de vue du programmeur Par exemple imaginons qu on doive ajouter syst matiquement la t te d une liste un compteur Si la liste est vide il est logique de continuer les calculs en n ajoutant rien au compteur Dans ce cas l chec signal par la fonction t te doit tre r cup r On utilise pour cela la construction try with try signifie essayer et with avec qui permet de calculer une expression en surveillant les exceptions que son calcul peut d clencher Cette construction ob it la syntaxe suivante try expression with filtrage Elle signifie intuitivement essayer de calculer la valeur de expression et si cette valuation d clenche une erreur qui tombe dans un des cas du filtrage alors retourner la valeur correspondante de la clause s lectionn e par le filtrage Par exemple puisque l erreur signal e par la fonction t te est Failure t te on envisagera cet chec dans la partie filtrage du try with pour renvoyer une valeur enti re comme si aucune erreur n avait t d clench e On rattrape donc l chec sur la liste vide et
382. luation de compte 2 qui crit 2 et retourne compte 3 et ainsi de suite Nous allons utiliser le m canisme de trace de Caml pour suivre les appels r cursifs et les impressions Ce m canisme imprime l cran les appels successifs d une fonc tion ainsi que les r sultats que la fonction calcule Tra ons par exemple la fonction successeur let successeur x x 1 successeur int gt int lt fun gt trace successeur La fonction successeur est dor navant trac e unit successeur 2 successeur lt 2 successeur gt 3 int 3 Vous lavez devin l appel d une fonction est indiqu par le signe lt suivi de l argument concern tandis que le signe gt signale un retour de fonction et affiche le r sultat obtenu Nous suivons maintenant le d roulement des appels compte et compte_ _rebours trace compte trace compte_ _rebours La fonction compte est dor navant trac e La fonction compte_ _rebours est dor navant trac e unit compte 3 compte lt 3 compte lt 2 compte lt 1 compte lt 0 compte gt 1 compte gt 24 R cursivit 2 compte gt 3 compte gt unit On voit clairement que compte s ach ve avant l impression de 1 et que compte 0 se termine avant toute impression Cela contraste avec compte_ _rebours qui imprime i avant l appel compte_ _rebours i
383. luder les difficult s mini Caml pr sente toutes les particularit s essentielles de Caml pleine fonctionnalit filtrage polymorphisme Cette tude nous donnera galement l occasion d claircir un certain nombre de points d licats du langage Caml lui m me aussi bien dans le domaine de l ex cution des programmes que dans celui de la synth se des types Ces points d licats se manifestent rarement lorsqu on programme en Caml nous ne les avons pas encore rencontr s dans ce livre mais apparaissent nettement lorsqu on impl mente Caml Dans ce chapitre nous commen ons notre tude par la r alisation d un interpr teur mini Caml non typ Le prochain chapitre aborde la synth se et la v rification statique des types 17 1 Le langage mini Caml Comme d habitude d finissons d abord la syntaxe abstraite du langage mini Caml que nous tudions Comme on le voit ci dessous nous n avons conserv que les con structions essentielles de Caml l acc s un identificateur la d finition de fonctions par filtrage l application de fonctions et la liaison let r cursive ou non S y ajoutent deux types de base les entiers et les bool ens et deux structures de donn es les paires et les listes Fichier syntaxe mli type expression Variable of string Fonction of motif expression list 326 Ex cution d un langage fonctionnel Application of expression expression Let of d finition exp
384. lusion notre fonction ins re fonctionne P est vraie pour toute liste Donc si l est une liste bien tri e ins re l ment l est bien tri e et comprend l ment en plus la recherche de l it rateur unique 105 de tous les l ments de la liste l Les propri t s des fonctions d finies sur les listes se d montreront toujours de fa on analogue en suivant le filtrage utilis par la fonction pour diriger la preuve par induction structurelle induction signifie d monstration par r currence 5 12 la recherche de l it rateur unique Nous avons r ussi exprimer la fonction implose en fonction de it_list et de list_it La question se pose donc du choix de l it rateur le plus efficace et de l utilit d en avoir deux R cursivit terminale En ce qui concerne l efficacit it_list est l g rement plus efficace que list_it car il est r cursif terminal ce qui signifie qu il peut s impl menter en machine par un simple saut il ne laisse pas de calculs en suspens Par exemple la fonctionnelle do_list est r cursive terminale let rec do_list f function 10 gt 0O x l1 gt f x do_list f l do_list a gt b gt a list gt unit lt fun gt En effet apr s avoir ex cut f x on rappelle directement do_list en oubliant le calcul pr c dent En revanche map n est pas r cursive terminale let rec map f function a gt 0 x 1 gt f x map f l map
385. lution comme int bool g n ralisation t transforme le type t en un sch ma de types avec pour param tres toutes les inconnues introduites lors du ty page de la pr c dente d finition sp cialisation s transforme le sch ma de types s en un type simple en rempla ant les param tres du sch ma par de nouvelles inconnues de typage sch ma_trivial t transforme le type t en un sch ma de types trivial c est dire sans aucun param tre Sert m langer dans la m me structure d environnement de vrais sch mas de types tels que ceux obtenus par la construction let et des types simples tels que les types des arguments des fonctions d but_de_d finition signale que l on commence le typage de la partie d finition d un let fin_de_d finition signale que l on sort du typage de la partie d finition d un let et qu on est sur le point de typer la partie in imprime_type t affiche le type t l cran imprime_sch ma s m me chose pour un sch ma Le module synthese fournit deux fonctions l une qui d termine le type d une expression l autre qui d termine le type d une d finition Les deux fonctions sont param tr es par un environnement de typage qui associe des sch mas de types aux identificateurs libres de l expression Fichier synthese mli open syntaxe open types type environnement string sch ma_de_types list value type_exp environnement
386. machine produira l instruction Op Store 30 Imm 1 1 Comme pour un processeur r el l assembleur effectue un codage des op rations au contraire d un processeur r el le code n est pas sous forme binaire Il aurait t possible de coder r ellement en nombres entiers au prix d inutiles complications Un autre service que rend l assembleur est de lib rer le programmeur de la gestion des num ros d instructions On crit les instructions la suite et l assembleur les range automatiquement par num ros croissants Bien plus il fournit la possibilit de rep rer des instructions par des noms ce sont les tiquettes symboliques qui font r f rence des adresses d instructions sans que le programmeur ait calculer l adresse ab solue de l instruction correspondante dans la zone code Ce remplacement automatique d adresses symboliques par des adresses absolues s appelle la r solution des tiquettes Le langage d assemblage tel qu il est d fini par l assembleur est donc plus riche et plus expressif que le langage ex cut par la machine puisqu il comporte ces tiquettes symboliques L assembleur fournit galement un certain nombre d abr viations par exemple sp est un nom de registre l gal de l assembleur qu il transforme automatique 268 Simulation d un processeur ment en une r f rence au registre num ro 30 Il s agit l encore de noms symboliques automatiquement g r s par l
387. mais la d finition pr c dente de s reste inchang e Pour s en rendre compte il suffit de demander la valeur de s c est dire le r sultat du calcul r duit s s int 6 La d finition locale d un nom est compl tement ind pendante du type actuel du nom par exemple s et s2 qui sont actuellement de type int peuvent tre d finis localement avec le type string let s Le langage and s2 Caml in s s2 string Le langage Caml Cet exemple utilise l op rateur qui met deux cha nes de caract res bout bout con cat nation Notez galement que les d finitions multiples consistent en une simple succession de d finitions s par es par le mot cl and qui signifie et 1 4 Fonctions Les fonctions forment les constituants l mentaires des programmes en Caml Un programme n est rien d autre qu une collection de d finitions de fonctions suivie d un appel la fonction qui d clenche le calcul voulu Fonctions 9 D finir une fonction D finir une fonction en Caml est simple et naturel car la syntaxe est tr s proche des notations math matiques usuelles la d finition math matique soit successeur la fonction d finie par successeur x x 1 correspond la d finition Caml suivante let successeur x x 1 successeur int gt int lt fun gt Caml nous indique encore une fois que nous avons d fini un nom successeur Ce nom a pour type int gt
388. mbre de lignes d une table de v rit est 2 o n est le nombre de variables qui interviennent dans la table Notre fonction v rifie_tautologie suit exactement la m thode des tables de v rit elle a donc une complexit exponentielle Ce n est pas tr s grave pour nous car nous nous limiterons trois variables au plus C est un probl me actuellement ouvert que de savoir s il existe des algorithmes d une meilleure complexit que le n tre pour calculer la table de v rit d une formule Dans le pire des cas on ne sait videmment pas faire mieux mais dans certains cas particuliers on parvient calculer les tables de v rit de formules o interviennent des centaines voire des milliers de variables ce qui est absolument hors de port e de notre programme On utilise pour cela des structures sophistiqu es de partage de tables de v rit comme par exemple les binary decision diagrams Calcul des variables libres Pour appeler la fonction v rifie_tautologie nous devons disposer d une fonction qui d termine l ensemble des propositions l mentaires d une proposition ce que nous appelons aussi ses variables libres La liste des variables libres s obtient facilement par un parcours r cursif de la proposition la recherche de sous propositions de la forme Variable v Fichier prop ml let rec variables accu proposition match proposition with Variable v gt if mem v accu then accu else v accu No
389. ment la strat gie par d faut est de choisir une phrase de relance de la conversation c est donc la clause with du dernier try Lorsque les r ponses possibles la phrase entr e sont trouv es il ne reste qu en choisir une au hasard et l imprimer exception Fini L exception Fini est d finie let r pond_au_patient r ponse let r minuscules r ponse in let phrase divise_en_ mots r in if c est_fini phrase then raise Fini else let r ponses_possibles try associ _de synonyme_de_phrase phrase r ponses_aux_phrases_simples with Pas_trouv gt try associ _d un_ l ment_de phrase r ponses_aux_mots_int ressants with Pas_trouv gt if caract re_dans_cha ne r then r ponses_types else try associ _d un_ l ment_de phrase r ponses_aux_petits_mots with Pas_trouv gt relances in message au_choix_dans r ponses_possibles print _newline r pond_au_patient string gt unit lt fun gt Le programme lui m me it re les fonctions coute_le_patient et r pond_au_patient en surveillant la fin de l interaction L interruption inopin e de la consultation est rat trap e pour rappeler la politesse l utilisateur l interruption d un programme Caml d clenche une exception pr d finie sys__Break dans le syst me Caml Light let cam lia bonjour try while true do r pond_au_patient coute_le_ patient done with Fini gt au_revoir Exemple d
390. ment ne poss de quand m me qu un seul argument et non pas deux La fonction addition ci dessus qui prend un seul argument qui se trouve tre une paire est diff rente de la fonction add suivante qui prend deux arguments let add x y x y add int gt int gt int lt fun gt Du point de vue pratique la diff rence est minime il est vrai D un point de vue tech nique une fonction qui re oit ses arguments un par un comme add est dite curryfi e En revanche une fonction qui re oit tous ses arguments la fois sous la forme d une paire ou plus g n ralement d un n uplet de valeurs est dite non curryfi e Le n ologisme curryfer n est pas une allusion la cuisine indienne mais un hommage au logicien Haskell Curry Application partielle La diff rence essentielle entre add et addition tient dans la mani re de les appli quer il est l gal d appliquer la fonction add un seul argument obtenant ainsi une fonction comme r sultat tandis que la fonction addition doit forc ment recevoir ses deux entiers en m me temps Cette capacit des fonctions curryfi es de ne recevoir qu un certain nombre de leurs arguments permet l application partielle Par exemple en appliquant partiellement add l entier 1 on obtient la fonction successeur let successeur add 1 successeur int gt int lt fun gt successeur 3 int 4 Curryfication et type fl che Une fonction curryfi
391. ment parenth s es Par exemple successeur 2 successeur 3 est lu comme successeur 2 successeur 3 et de m me pour tous les op rateurs successeur 2 gt successeur 3 est correctement interpr t fz guy est quivalent fx g y Application de fonctions plusieurs arguments L application de fonctions plusieurs arguments suit les m mes conventions moyenne 2 6 est quivalent moyenne 2 6 mais vous devez conserver les parenth ses si vous voulez calculer moyenne 2 x 3 3 3 Techniquement on dit que l application associe gauche en Caml ce qui signifie que les parenth ses peuvent tre omises dans f x y qui correspond au r sultat de f de x appliqu y mais qu elles sont indispensables dans f g x qui signifie au contraire f appliqu e au r sultat de l application de la fonction g x fxy est quivalent fx y Au lieu de moyenne 2 6 on peut donc crire moyenne 2 6 La deuxi me forme est videmment un peu trange mais elle a la m me signification que la premi re On a donc beaucoup de mani res quivalentes d exprimer l application de la fonction moyenne 2 et 6 La plus simple est videmment sans parenth ses aucunes moyenne 2 6 Mais l on peut crire aussi moyenne 2 6 ou en utilisant la r gle pr c dente pour ajouter encore des parenth ses moyenne 2 6 ou m me moyenne 2 6 En pratique nous utiliserons to
392. ment valables pour un ensemble d termin de types Par exemple il n y a aucun moyen de d finir une fonction qui s appliquerait uniquement des entiers et des cha nes de caract res et qui aurait donc un type du genre int ou string gt Un programme Caml s applique soit tous les types possibles soit un seul et unique type Dans le premier cas le type du programme comporte un param tre par exemple a gt dans le second cas il n en comporte pas par exemple int gt Voyons un premier exemple let successeur x x 1 successeur int gt int lt fun gt La fonction est monomorphe comme on s y attend elle ne s applique qu des entiers puisqu on doit faire une addition avec son argument Mais supposons qu on supprime l addition qui entra ne cette contrainte sur l argument x et qu on renvoie directement 1 let fonction_un x 1 fonction_un a gt int lt fun gt La fonction fonction_un est maintenant polymorphe elle ne fait rien de son argument on peut donc l appliquer n importe quoi fonction_un 2 fonction_un oui fonction_un true int 1 int 1 int 1 Contrairement ce que sugg re l exemple fonction_un une fonction polymorphe peut utiliser son argument par exemple en le renvoyant tel quel Nous supprimons encore une fois l addition dans le code de successeur mais cette fois nous renvoyons x au lieu de 1
393. mentation ml consulte le zi pour v rifier la coh rence si l interface mli n existe pas alors la compilation de l impl mentation ml cr un zi qui rend public tout ce que l impl mentation ml d finit Il en d coule deux contraintes sur l ordre dans lequel on effectue les compilations d une part l interface explicite mod mli doit tre compil e avant tous les fichiers ml et mli qui font r f rence au module mod d autre part l interface explicite mod mli doit tre compil e avant l impl mentation mod ml Dans le cas du mini Logo il en d coule les contraintes suivantes cra yon ml langage ml asynt ml logo ml alex ml S crayon mli langage mli asynt mli alex mli Interfaces de modules 189 Fichier alex mli Fichier crayon mli value vide_ cran unit gt unit and fixe_crayon bool gt unit and tourne float gt unit and avance float gt unit Fichier crayon ml open graphics let round x type tat let crayon let avance d let pi_sur_180 let tourne angle let avance d let couleur _du_trac let couleur_du_fond let z ro_x Es ce let z ro_y let vide_ cran type lex me value analyseur_lexical char stream gt lex me stream Fichier alex ml let rec saute_blancs let rec lire_entier let rec lire_ d cimales let rec lire_mot
394. mitives lineto et moveto pour dessiner le flocon Tout simplement parce qu il faut leur pr ciser les coordonn es absolues des points du trac ce qui signifierait pour le flocon calculer les coordonn es de toutes les extr mit s des segments qui forment le flocon Cela para t vraiment difficile En revanche nous d crirons facilement les mouvements relatifs du crayon le faisant tourner et avancer tour tour D autre part le rep re du graphisme de Caml ne comporte que des points dont les coordonn es sont enti res puisqu il s agit de points de l cran Cependant pour des raisons de pr cision du trac du crayon nous maintiendrons les coordonn es du crayon en nombres d cimaux Il nous faudra donc arrondir les coordonn es du crayon avant d effectuer ses d placements sur l cran 8 3 Les nombres en repr sentation flottante L impl mentation du crayon n cessite donc des nombres virgule et plus pr cis ment virgule flottante qui sont fournis en Caml par le type pr d fini float On les appelle nombres flottants en jargon informatique Ils sont caract ris s par leur virgule mais la virgule dans les nombres se note avec un point en anglais naturellement c est la notation avec un point qui s est impos e en informatique Le nombre 3 5 se note donc 3 5 en Caml De m me les op rations de base sur les flottants op rations arithm tiques et comparaisons ont pour nom celui de l op ration corresp
395. mme est traditionnellement appel l assembleur Il produit une suite d instructions directement ex cutables qu il crit dans un fichier de r sultat Ce fichier est ensuite lu et charg en m moire programme la demande de l utilisateur par un programme sp cial qui lance l ex cution En g n ral ce lanceur est le syst me d exploitation de l ordinateur dans notre cas c est le programme pico_run de la sec tion pr c dente Le langage de l assembleur Le langage d entr e de l assembleur s appelle en termes pr cis le langage d assemblage et par abus l assembleur Le mot assembleur a donc deux sens en informatique il d signe tant t un langage tant t un programme de traduction Pour viter toute confusion nous emploierons langage d assemblage pour le langage d instructions symboliques et assembleur pour le programme Le principal travail de l assembleur est de lire une repr sentation textuelle des in structions de la machine et de la transformer en code ex cutable Dans un processeur r el le code ex cutable est une suite d octets ou de mots qui encodent les instructions et leurs op randes sous forme binaire Pour la pico machine la phase de transformation du programme source en suite de nombres sera remplac e par la traduction en syntaxe abstraite des instructions de la pico machine Par exemple on crira store sp 1 r 1 dans le langage d assemblage et l assembleur de la pico
396. mot cl rec Examinez les fonctions d valuation des ordres et de d finition des proc dures vous remarquerez qu une proc dure est toujours d finie sans examen de son corps Rien ne l emp che donc de faire r f rence une autre proc dure pas encore d finie en particulier elle peut faire r f rence elle m me Lors de l ex cution il n y a pas de probl me non plus on va rechercher la d finition de la proc dure autant de fois que n cessaire et cette recherche r ussit toujours puisque la proc dure est d finie Puisque la r cursivit est automatique en mini Logo vous devinez que la diff rence de Caml mini Logo n ob it pas la r gle de port e statique En effet lors de l ex cution du corps d une proc dure quand on rencontre un identificateur on interroge l environnement courant on va donc trouver la valeur actuellement li e au nom Cette liaison a t tablie au cours de l ex cution du programme elle n est pas celle qu on obtiendrait en examinant le texte du programme Ce type de port e des identificateurs se nomme la port e dynamique Il est donc l gal en mini Logo d utiliser une proc dure avant de l avoir d finie 10 Programmes ind pendants et modules O l on apprend diviser pour r gner sur ses programmes USQU ICI nous avons utilis Caml d une mani re enti rement interactive l utilisateur entre une phrase le syst me l ex cute l uti
397. motif on avance en fait lin airement de 3d C est donc que si chacun des morceaux mesure d la longueur totale du motif est 3d Comme cette longueur totale est c on en d duit que 3d c et donc d c 3 On obtient la proc dure suivante let rec motif n c if n O then avance c else begin motif n 1 c motif n 1 c motif n 1 c motif n 1 c end motif int gt float gt unit lt fun gt 3 0 tourne 60 0 8 0 tourne 120 0 3 0 tourne 60 0 8 0 SN Le flocon la nm g n ration s obtient simplement en tra ant 3 fois le motif de g n ration n sur les trois c t s d un triangle quilat ral let flocon n c for i 1 to 3 do motif n c tourne 120 0 done flocon int gt float gt unit lt fun gt vide_ cran vide_ cran vide_ cran flocon 2 100 0 flocon 3 100 0 flocon 4 100 0 unit unit unit Impressionnant n est ce pas 9 Syntaxe abstraite syntaxe concr te Un peu de recul permet souvent d avancer OUS NOS OUTILS GRAPHIQUES sont maintenant en place et nous sommes pr ts transformer les programmes de pilotage du crayon lectronique en un v ritable langage de programmation Ce chapitre introduit donc la notion de syntaxe abstraite et pr sente un exemple d valuation d arbres de syntaxe abstraite Nous aborderons aussi l important concept d analyse syntaxique Nous esquis serons ainsi
398. mp amp v rifie_lignes proposition var false liaisons autres Cette version n est pas plus claire que la pr c dente elle est trompeuse car bien qu elle semble calculer un bool en son r sultat n est pas int ressant En effet elle retourne toujours le bool en true si la proposition est une tautologie ou l ve une exception si la proposition est r futable C est donc bien une proc dure puisqu elle fonctionne par ef fets l effet attendu est soit valuation r ussie soit un d clenchement d exception Il ne sert rien de la d guiser en fonction Si l on renonce renvoyer une r futation de la proposition analys e il est possible d crire une vraie fonction qui calcule vraiment un bool en Malheureusement on perd la liaison des variables qui a prouv que la propo sition n est pas une tautologie et il faut alors crire une autre fonction compl tement analogue pour renvoyer une r futation Cet exemple nous montre un autre int r t des exceptions dans certains cas une fonction peut calculer en fait deux r sultats de type diff rent l un v hicul par le m canisme normal des appels de fonctions l autre transport par une exception v rifie_lignes calcule un bool en dans le cas d une tautologie et une liste d association nom de variable valeur bool enne dans le cas contraire 216 D monstration de propositions Une remarque de complexit comme nous l avons d j vu le no
399. mpilateur le programme qui r alise la compilation est forc ment complexe et long c est un bon crit re de savoir que le compilateur est capable de le compiler sans erreurs en produisant un code acceptable en un temps raisonnable C est une tape majeure dans la validation d un langage de programmation et de son impl mentation Rappelons encore une fois que tous les syst mes Caml sont autog nes L auto g n ration d un compilateur Caml serait donc une belle aventure raconter mais ceci est une autre histoire Index chec 77 126 criture d une r f rence 48 criture dans un enregistrement 119 150 criture dans un tableau 41 criture dans une cha ne 46 criture sur fichier 182 dition de liens 187 galit 43 121 316 galit physique 354 num r s types 113 quivalence 211 tiquette 117 tiquettes d assemblage 267 toile 42 valuation paresseuse 162 334 1 47 354 Med UReE 6 148 open 184 amp amp 26 214 O 14 10 63 10 149 149 gt 11 28 63 65 117 149 CAT 24 46 133 164 11 75 48 3 14 es 0 lt 41 46 119 150 164 lt gt 43 214 316 354 92 102 C 75 lt gt 162 163 165 75 I 1 40 8 68 88 100 _ 28 85 Eege CIDA 116 28 110 135 163 1 26 214 _a 87 364 162 a 58 abr viatio
400. n lt d finition _d tiquette instruction_ tiq O gt gt O K instruction gt gt let rec suite _d instructions flux match flux with lt instruction _ tiq gt gt suite _d instructions flux I K gt gt 0 let analyseur_lexical construire_analyseur r sp ya load store nada muit sub ndiy and or xor shl shr z sgt n sge n sne n slt n a e seq jmp braz A branz scall write read stop Mag wear 5 let programme flux initialise suite_d instructions analyseur_lexical flux extraire_code L assemblage d un fichier complet L assemblage d un fichier consiste simplement le lire en m moire l assembler en r solvant les tiquettes puis crire le tableau des instructions sur le fichier de sortie sp cifi La seule difficult consiste g rer les cas d erreur Fichier asm ml let assemble_fichier nom_entr e nom_sortie let entr e open_in nom_ entr e in let sortie open_out_bin nom_ sortie in try output_value sortie lecture__programme stream_of_channel entr e close_in entr e close_out sortie 0 with exc gt close_in entr e close_out sortie sys__remove nom_sortie match exc with Parse_error Parse_failure gt prerr_string Erreur de syntaxe aux alentours du caract re num ro prerr_int p
401. n Le m me axiome est vrai en Caml vous ne pouvez utiliser un identificateur s il n a re u une d finition pr alable C est ce qu on appelle la port e statique parce que vous pouvez trouver la d finition de n importe quel identificateur ind pendamment du comportement du programme l ex cution au contraire de la port e dynamique o la valeur d un identificateur d pend de la fa on dont le calcul se d roule En Caml pour une occurrence quelconque d un identificateur disons x il vous suffit d examiner le texte du programme qui pr c de x pour trouver la liaison qui a d fini x Cette liaison est soit une d finition de x let x soit une d finition de fonction qui a x pour param tre function x gt Fonctions r cursives simples 21 let x 1 in let x x 1 in x 3 int 5 L identificateur x qui appara t dans x 1 dans la d finition let x x 1 est li 1 par la pr c dente d finition let x 1 alors que le dernier x dans x 3 est li 2 par la pr c dente d finition let x x 1 comme le sugg re ce sch ma let x 1 in let x 1 in 3 Le m canisme de liaison est similaire pour des d finitions simultan es d finitions s par es par le mot cl and let x 1 in let x x 1 and y x 2 in x y int 6 Les deux x intervenant dans les d finitions let x and y font tous les deux r f rence au nom x pr c demment d fini par let
402. n nombre_de_caract res_ _transf rer transf re nombre_de_caract res_ _ transf rer dans la cha ne destination partir de l indice indice_destination Ces caract res sont ceux de la cha ne source partir de l indice indice_source nombre_de_caract res_ _transf rer e indice_source destination ejojojojojojojojo indice_destination source Pour calculer la complexit de la fonction implose nous consid rerons que le co t d une concat nation est ind pendant de la longueur des deux cha nes concat n es ou encore que toutes les cha nes sont d gale longueur et m me de longueur 1 pour simplifier encore Nous supposons que la liste argument lc comprend n cha nes c1 C2 Cn chaque cha ne c de la liste de cha nes argument on recopie le pr c dent r sultat dans une nouvelle cha ne f puis on recopie la cha ne c dans f On alloue donc autant de cha nes que de r sultats interm diaires soit n De plus c est recopi e une fois C2 deux fois et Cn est recopi e n fois Ce qui donne donc 1 2 3 n caract res copi s Or un calcul facile il suffit d ajouter les termes de la somme en les groupant astucieusement premier avec dernier deuxi me avec avant dernier etc montre que n x n 1 1 2 3 n 5 Efficacit de
403. n Caml let rec associ _d un_ l ment_de liste_de_cl s liste_d association match liste_de_cl s with gt raise Pas_ trouv cl reste gt try associ _dans_liste cl liste_d association with Pas_trouv gt associ _d un_ l ment_de reste liste_d association associ _d un_ l ment_de a list gt a list b list gt b lt fun gt Traitements de cha nes de caract res 133 7 4 Traitements de cha nes de caract res Notre programme va effectuer une certaine normalisation de l entr e de l utilisateur passer syst matiquement toute la phrase en minuscules et ter les signes de ponctuation et accents ventuels par exemple Les fonctions correspondantes illustrent le traitement de cha nes de caract res en Caml Passage en minuscules En machine les caract res sont videmment enregistr s comme des nombres Le codage utilis en Caml s appelle le code ASCII Il suffit de le faire imprimer par Caml pour comprendre comment sont rang s les caract res de l alphabet remarquez aussi les chiffres for i 32 to 126 do if i lt 100 then print_string print_int i print_ string print_char char_of_int i print_string if i mod 8 7 then print_newline mon LLERS done print _newline 32 33 34 35 36 87 38 amp 39 40 41 42 43 44 45 46 47 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 56 8 57 9 58 59 60 lt 6
404. n de Thompson Les automates qu il produit ont la particularit d avoir un seul tat terminal qu on appelle l tat final par sym trie avec l tat initial De plus aucune transition ne sort de l tat final On introduit le type automate_de_thompson pour garder en m me temps un pointeur sur l tat initial et un pointeur sur l tat final de l automate La construction de Thompson proc de par r currence sur la structure de l expression rationnelle Pour les deux cas de base Epsilon et Caract res c1 c on renvoie les deux automates suivants C1 OO X O Clairement l automate de gauche reconna t uniquement le mot vide et l automate de droite uniquement les cha nes mono caract res c1 Cn Pour le cas S quence r1 r2 on construit r cursivement les automates de Thompson correspondant r et r2 et on met une transition tiquet e de l tat final de l automate pour r vers l tat initial de l automate pour r2 J thompson r O thompson ro O a 2 Rs _ L automate r sultant reconna t les concat nations d un mot reconnu par thompson r et d un mot reconnu par thompson r2 Il reconna t donc bien les m mes mots que l expression rationnelle S quence r1 r2 En suivant un raisonnement semblable on prend pour les cas Alternative r1 r2 et R p tition r D terminisation de l automate 313 thompson r1 Pi thompson rz ed
405. n de type 261 abstraction 66 81 91 acc s dans un tableau 41 acc s direct dans les fichiers 246 accumulateur 47 49 61 102 216 affectation 37 41 48 54 al atoires nombres 140 201 allocation m moire 290 367 alternative 12 26 43 analyse de cas 28 analyse lexicale 160 162 217 228 analyse syntaxique 159 160 166 173 218 271 279 308 336 365 and 8 appel par n cessit 334 374 appel par nom 334 appel par valeur 334 appels syst me du pico processeur 265 application 9 16 73 application partielle 64 67 221 231 arbres de Huffman 242 arbres tournoi 248 argument n gatif 15 arguments d une commande 240 as 80 117 ASCII code 133 163 assembleur 267 associativit 16 auto g n ration 371 automates 309 automates d terministes 313 begin 14 belote 115 bien fond e r cursion 19 22 bind 197 bit bit op rations 250 bloc d activation 291 BNF 17 bool ens 13 26 bootstrap 371 bouclage 8 boucle d interaction 142 183 193 222 332 358 boucles 39 41 49 51 61 68 101 129 bouton 193 cadre 194 Cam lia 125 CamlTk 193 canaux d entr e sortie 182 183 caract ristique 117 caract res 24 46 cartes 115 cas inutiles dans le filtrage 120 cha nes de caract res 24 25 46 66 88 129 133 champ 117 chargement de fichiers 179 circulaires types 354 codage de Huffman 241 242
406. n dehors de la m moire adresse if adresse mod taille_du_mot lt gt 0 then raise Erreur lecture non align e adresse pico m moire adr let crire m moire adresse valeur let adr adresse taille _ du mot in if adr lt O adr gt vect_length pico m moire then raise Erreur criture en dehors de la m moire adresse if adresse mod taille_du_mot lt gt 0 then raise Erreur criture non align e adresse pico m moire adr lt valeur let valeur_op rande function Reg r gt lire_registre r Imm n gt gt n Dans le cas des acc s la m moire il faut tenir compte du fait que l adresse d un mot est toujours multiple de 4 il faut donc la diviser par 4 pour obtenir l indice qui lui correspond dans le tableau pico m moire Fichier simul ml let tableau_des_appels_syst me make_vect 10 function x gt x int gt int let ex cute_appel_syst me appel argument if appel lt O appel gt vect_length tableau_des_appels_syst me then raise Erreur mauvais appel syst me appel else tableau_des_appels_syst me appel argument La fonction cycle_d horloge ex cute une instruction la fois elle d code et ex cute l instruction actuellement point e par le compteur ordinal PC puis incr mente ce compteur pour passer l instruction suivante Dans cette fonction les op rations de la machine sont simul es l aide de fonctions Caml
407. n incorrecte de ces cas difficiles L auto g n ration Quoi qu il en soit vous devez entrevoir maintenant les tapes principales d une impl mentation compl te de Caml en Caml description de la syntaxe abstraite de la syntaxe concr te du typage et enfin de la compilation Ce m canisme d auto description est g n ral dans les syst mes Caml il sont tous autog nes c est dire pro duits par eux m mes En effet le compilateur est enti rement crit en Caml c est donc un programme Caml comme tous les autres compilable par le compilateur Caml c est dire par lui m me Ce m canisme d auto amor age ou d auto g n ration s appelle bootstrap en anglais L auto g n ration est un m canisme trange puisqu il s agit d une sorte de d finition r cursive au niveau de la sp cification ex cutable du compilateur du lan gage On se demande bien par quel miracle il en sort un syst me Caml qui tourne C est simplement que la r cursion s arr te sur le compilateur de niveau z ro le compilateur initial qui est toujours crit dans un autre langage Progressivement certaines parties du compilateur initial sont r crites dans le langage compilable par le compilateur jusqu obtenir finalement un compilateur enti rement crit dans le langage du compilateur le langage est devenu autog ne Au del du tour de force qu elle constitue l auto g n ration est un gage de qualit pour un co
408. n le voit bien l aide de la fonction pr d finie stream_next qui renvoie le premier l ment d un flux stream_next flux _car char V stream_next flux _car char i Ce comportement de lecture destructrice est bien adapt l analyse lexico syntaxique en g n ral les analyseurs lisent une seule fois leur entr e sans jamais revenir en arri re il ne sert donc rien de conserver les l ments de l entr e une fois qu ils ont t lus La deuxi me particularit des flux est que les l ments contenus dans un flux ne sont pas valu s en bloc quand le flux est cr mais petit petit au fur et mesure qu on y acc de En particulier lorsqu on construit le flux des caract res provenant d un fichier ce dernier n est pas lu tout entier en m moire le flux ne contient en m moire que le caract re courant et va chercher le prochain caract re sur le disque lorsqu on en a besoin Ce comportement est conomique en m moire en particulier quand le fichier est gros En termes savants ce proc d s appelle valuation paresseuse par analogie avec la strat gie bien connue consistant remettre demain ce qu il n est pas absolument n cessaire de faire aujourd hui Analyse lexicale L analyse lexicale consiste transformer un flux de caract res en le flux des lex mes correspondants avons nous dit Nous allons nous fixer un but plus modeste construire une fonct
409. n p gt variables accu p Et p q gt variables variables accu p q Ou p q gt variables variables accu p q Implique p q gt variables variables accu p q quivalent p q gt variables variables accu p q _ gt accu let variables_libres proposition variables proposition La seule difficult est que les variables ne doivent pas tre r p t es dans la liste r sultat Par exemple si on cherche les variables de la proposition P et P on va rencontrer deux fois le terme Variable P Pourtant la cha ne P ne doit appara tre qu une fois dans le r sultat de variables_libres C est pourquoi lorsqu on rencontre Variable v on teste si v n appartient pas d j la liste des variables collect es jusqu pr sent l aide de la fonction pr d finie mem qui se comporte comme la fonction membre de la section 7 3 La fonction variables maintient donc un accumulateur des variables d j collect es c est l argument accu qu on g re soigneusement lors des appels r cursifs Par exemple dans le cas d un op rateur binaire comme et on appelle r cursivement variables sur le deuxi me argument de l op rateur mais avec un accumulateur obtenu en collectant les variables du premier argument Et p q gt variables variables accu p q La fonction principale variables_libres se r duit l appel de variables avec un accumulateur initialement vide Synta
410. n re oit avec la construction try with La s mantique de try e with filtrage est de retourner la valeur de e si e s value normalement c est dire sans d clenchement d exception En revanche si une valeur exceptionnelle est d clench e pendant l valuation de e alors cette valeur est filtr e avec les clauses du filtrage et comme d habitude la partie expression de la clause s lectionn e est renvoy e Ainsi la partie filtrage de la construction try with est un filtrage parfaitement ordinaire op rant sur des valeurs du type exn La seule diff rence est qu en cas d chec du filtrage la valeur exceptionnelle qu on n a pas pu filtrer est propag e c est dire d clench e nouveau Comparez ainsi une valuation habituelle try t te 1 with Failure t te gt O ant une valuation d clenchant une valeur exceptionnelle rattrap e try t te with Failure t te gt O int 0 et finalement une propagation de valeur exceptionnelle try t te with Failure reste gt O Exception non rattrap e Failure t te D finition d exceptions De nombreuses fonctions pr d finies de Caml quand elles chouent d clenchent l exception Failure avec leur nom comme argument C est pourquoi l exception Failure poss de un d clencheur pr d fini la fonction failwith Nous pouvons maintenant crire sa d finition let failwith s raise Failure s
411. n rencontre un identificateur non qualifi qui n est pas d fini dans le fichier en cours de compilation il faut le chercher dans le module argument de open Par exemple dans le fichier asynt ml apr s la ligne open langage on peut faire r f rence au type ordre et ses constructeurs par des identificateurs sim ples Av Re Sans le open il aurait fallu utiliser des noms qualifi s 1angage__Av Plusieurs directives open dans un fichier donnent ainsi au compilateur une liste de modules o aller chercher les identificateurs externes Le choix entre ces deux mani res de faire r f rence un nom ext rieur est une pure question de style l emploi de open donne des programmes plus compacts et permet de renommer les modules plus facilement l emploi de noms qualifi s montre plus clairement la structure modulaire du programme La biblioth que de modules du syst me Il n y a pas que les programmes de l utilisateur tre d coup s en modules la bib lioth que de fonctions pr d finies du syst me Caml Light se pr sente elle aussi sous la Programmes en plusieurs modules Fichier crayon ml open graphics let round x type tat let crayon let avance d let pi_sur_180 let tourne angle let avance d let couleur_du_trac let couleur_du_fond let z ro_x let z ro_y let vide_ cran ER 1
412. n sub_string provient du module de biblioth que string de m me des op rateurs comme et ne sont pas enti rement pr d finis dans le syst me mais proviennent de modules de biblioth que les modules int et float respectivement Certains de ces modules de biblioth que comme int float et string sont implicitement ouverts au lancement du compi lateur Tout se passe comme si on avait mis au d but de tous les fichiers open int open float open string C est ce qui explique qu on r f rence directement sub_string dans n importe quel programme sans mettre au pr alable open string ni devoir utiliser la forme compl tement qualifi e string__sub_string D autres modules de biblioth que d un emploi moins fr quent ne sont pas ouverts automatiquement au d but de chaque compilation C est le cas par exemple du module graphics fournissant les commandes graphiques de base Il faut donc mettre open graphics au d but du fichier crayon ml qui fait r f rence ces commandes graphiques Compilation s par e Les modules composant un programme se compilent un par un l aide de la com mande camlc c camlc c crayon ml camlc c langage ml camlc c alex ml camlc c asynt ml camlc c logo ml L option c indique au compilateur qu il ne faut pas essayer de produire un fichier de code ex cutable En d autres termes cette option pr vient le compilateur que le fichier
413. native si sont des listes d ordres et que la condition est forc ment la comparaison avec gt de deux expres sions Un petit d tail encore nous avons ajout la possibilit de taper directement des nombres n gatifs dans la fonction nombre En effet si le nombre commence par un signe nous rendons en r sultat son oppos en appelant la primitive Caml correspondant au type du nombre qui est simplement d termin par un filtrage explicite let rec analyse_programme function lt analyse_phrase ph analyse_programme p gt gt ph p lt Symbole gt gt 174 Syntaxe abstraite syntaxe concr te lt gt gt 0 analyse_phrase function lt Mot pour Mot s param tres variables suite_d ordres ordres Symbole gt gt Pour s param tres variables corps ordres lt ordre ord gt gt Ordre ord param tres function lt Symbole Mot s param tres 1 gt gt s 1 lt gt gt 0 ordre function lt gt Mot avance Mot av expression e gt gt Av e lt gt Mot recule Mot re expression e gt gt Re e lt gt Mot droite Mot td expression e gt gt Td e lt gt Mot gauche Mot tg expression e gt gt Tg e lt Mot baisse_crayon Mot bc gt gt Bc lt Mot l ve_crayon Mot lc gt gt Lc lt Mot vide_ cran Mot ve gt gt Ve
414. nce de compilation donn e ci dessus v rifie toutes les contraintes On a aussi la libert de compiler alex ml plus t t avant crayon ou langage dition de liens Lorsque tous les modules composant le programme ont t compil s il faut lier ensemble leurs fichiers de code objet obtenant ainsi un fichier ex cutable par camlrun Cette op ration s appelle l dition de liens et s effectue en appelant camlc avec la liste des fichiers en zo lier ensemble camlc o logo crayon zo langage zo alex zo asynt zo logo zo Comme pour un programme mono fichier l option o sert donner le nom du fichier ex cutable produire L ordre des fichiers zo sur la ligne a son importance il doit respecter la m me contrainte que pour l ordre des compilations savoir qu un module doit appara tre avant les modules qui l utilisent 10 5 Interfaces de modules Souvent un module contient des d finitions usage interne qui ne sont pas cens es tre employ es l ext rieur du module Dans le module crayon par exemple l enregistrement champs mutables qui contient l tat courant de la tortue n est pas cens tre modifi directement par les utilisateurs de ce module les utilisateurs sont suppos s passer par l interm diaire des fonctions avance tourne On peut s imposer de respecter cette convention soi m me mais le syst me est capable de la garantir si on lui demande explicitement de cacher certains de
415. nformatique non Je suis l pour vous aider Aimez vous vraiment l informatique Allez allez continuez Vous n aimez pas follement l informatique C est tout naturel m a t on dit l C tait vraiment facile LC famille Js Avez vous des fr res et soeurs let r ponses_aux_mots_int ressants Parlez moi de votre p re peur peurs Parlez moi de votre m re Parlez moi de vos frayeurs Voil qui m int resse norm ment Avez vous souvent peur Dites m en plus sur votre famille Avez vous des peurs inexpliqu es des La famille c est souvent compliqu cauchemars l pere mort morte morts Ressemblez vous votre p re l Je vous plains beaucoup Parlez moi encore de votre p re La mort est un sujet tr s grave Et votre m re Il faut essayer de prendre le dessus Votre p re Il faut pourtant quelquefois affronter la mere mort Ressemblez vous votre m re ou votre C est malheureux p re Essayez de ne plus y penser Parlez moi de votre m re malheureux malheureuse Parlez moi encore de votre m re probleme problemes Et votre p re l Racontez moi vos probl mes Votre m re Quels malheurs sont les v tres ami amis amie amies copains Avez vous vraiment des raisons de vous copines plaindre l Avez vous beaucoup d amis
416. ni transitions lt c n2 ni transitions let ajoute_eps_trans ni n2 ni epsilon_transitions lt n2 nl epsilon_transitions type automate_de_thompson initial tat final tat let rec thompson function Epsilon gt let e1 nouvel_ tat and e2 nouvel_ tat in ajoute_eps_trans e1 e2 initial e1 final e2 Caract res cl gt let e1 nouvel_ tat and e2 nouvel_ tat in do_list function c gt ajoute_trans e1 c e2 cl 312 Recherche de motifs dans un texte initial ei final e2 Alternative ri r2 gt let t1 thompson ri and t2 thompson r2 in let ei nouvel_ tat and e2 nouvel_ tat in ajoute_eps_trans e1 ti initial ajoute_eps_trans e1 t2 initial ajoute_eps_trans ti final e2 ajoute_eps_trans t2 final e2 initial ei final e2 S quence ri r2 gt let t1 thompson ri and t2 thompson r2 in ajoute_eps_trans ti final t2 initial initial ti initial final t2 final R p tition r gt let t thompson r in let ei nouvel_ tat and e2 nouvel_ tat in ajoute_eps_trans t final t initial ajoute_eps_trans el t initial ajoute_eps_trans t final e2 ajoute_eps_trans ei e2 initial ei final e2 let expr_vers_automate r let t thompson r in t final terminal lt true t initial L algorithme de transformation d une expression rationnelle en automate employ ci dessus est connu sous le nom de constructio
417. nique Parce que Syndr me du si Je ne r ponds pas aux questions des Vous n tes pas bavard vous au moins malades oui Si vous le savez pas ce n est pas moi I C est un peu rapide de vous l apprendre Donnez moi plus de d tails Personne ne peut r pondre cette Vous pourriez pr ciser question Je voudrais comprendre pourquoi Pensez vous qu une machine peut r pondre La r ponse n est pas si simple non a C est franc et massif au moins Ce serait trop long expliquer a ne m en dit pas vraiment plus Je sais bien pourquoi mais vous ne expliquez moi pourquoi comprendriez pas Vous tes s r C est difficile dire Soyez moins bref d veloppez aucun Plus laconique tu meurs Vraiment aucun 138 Le docteur Pas le moindre Qu entendez vous par malheur Le regrettez vous Bonheur malheur je n entends parler que C est un fait nouveau pour moi de a Continuez pas ennui ennuies ennuyez l a me semble un peu n gatif I L ennui a d pend de vous Vraiment Est ce que je vous ennuie Pourquoi cela Je le regrette pour vous Je ne m en serais pas dout e C est dommage pour vous Difficile C ennuis J ai l habitude d entendre a l Les ennuis sont souvent passagers M tes vous troubl ce point Tout ne peut pas tr
418. nition d f nom g n ralisation type_expr env Le typage des d finitions s pare nettement le cas r cursif du cas ordinaire Dans le cas ordinaire on type simplement l expression qui d finit l identificateur et l on ajoute le sch ma de types correspondant obtenu par la fonction g n ralisation 348 Un synth tiseur de types l environnement de typage Les appels d but_de_d finition et fin_de_d finition qui entourent le typage de l expression d finissante permettent g n ralisation de d tecter les inconnues qui doivent tre g n ralis es Dans le cas r cursif le m canisme est analogue mais on prend la pr caution de pr enregistrer l identificateur avec une nouvelle inconnue avant de typer l expression On unifie ensuite le type pr enregistr avec le type effectivement trouv pour l expression d finissante Comme dans le cas des fonctions l identificateur d fini r cursivement est pr enregistr avec un type inconnu il n est donc pas polymorphe dans l expression d finissante Ceci vous explique pourquoi la fonction identit re oit ici un type monomorphe let rec identit x x and message s print_string identit s identit string gt string lt fun gt message string gt unit lt fun gt 18 3 Repr sentation des types Passons l impl mentation du module types Les types simples et les sch mas de types sont repr sent s comme suit Fichie
419. nnecteurs que le non de la logique correspond bien au not de Caml de m me que et correspond amp amp et ou Nous supposerons cette d monstration faite dans la mesure o cette traduction est tr s naturelle et intuitive L implication est valu e en utilisant sa d finition P gt Q se calcule comme non P ou Q L quivalence est valu e en v rifiant simplement que ses deux arguments ont la m me valeur de v rit Le v rificateur de propositions Le principe du v rificateur est d valuer la proposition pour toutes les valeurs pos sibles de ses variables libres si l une des valuations renvoie faux alors la proposition n est pas une tautologie On signale ce fait en d clenchant l exception R futation avec pour argument une liste de paires cha ne bool en d crivant l ensemble des valeurs attribu es aux variables qui ont permis de calculer la valeur de v rit f pour la proposi tion Cette liste constitue bien une r futation de la proposition puisqu elle montre par un exemple que la proposition n est pas universellement vraie Repr sentation et v rification des propositions 215 Fichier prop ml let rec v rifie_lignes proposition liaisons variables match variables with RE if not value _ dans liaisons proposition then raise R futation liaisons var autres gt v rifie_lignes proposition var true liaisons autres v rifie_lignes proposition var fal
420. nnelle e L expression c o c est un caract re reconna t la cha ne un seul caract re c et rien d autre e L expression reconna t la cha ne vide et rien d autre e L expression e1 e2 reconna t les cha nes qui sont reconnues par e ou par ez e L expression eje2 reconna t les cha nes compos es d une cha ne reconnue par e1 suivie d une cha ne reconnue par e e L expression ex reconna t les cha nes compos es de z ro une ou plusieurs cha nes toutes reconnues par e Par exemple l expression cal ily ph f e reconna t quatre orthographes envisageables pour le mot calife De m me l expression 1Hle 0 1 2 3 4 5l6 7 8 9 0 11218141516 7 819 x reconna t toutes les repr sentations d cimales de nombres entiers ventuellement pr c d es d un signe 16 2 Syntaxe abstraite et syntaxe concr te des motifs Commen ons par construire un module expr d finissant la repr sentation interne syntaxe abstraite des expressions rationnelles ainsi qu une fonction pour lire une repr sentation textuelle syntaxe concr te d une expression rationnelle Voici l interface de ce module Fichier expr mli type expr Epsilon Caract res of char list Alternative of expr expr S quence of expr expr R p tition of expr value lire char stream gt expr La syntaxe abstraite le type concret expr suit de tr s pr s la d finition des ex pressions rationnelles donn
421. nnement environnement and environnement string valeur list value value environnement gt expression gt valeur and value_d finition environnement gt d finition gt environnement and imprime_valeur valeur gt unit exception Erreur of string La r gle de port e statique Nous devons donc expliquer pourquoi nous codons les fonctions par des fermetures qui comportent l environnement de d finition de ces fonctions Ceci est rendu n cessaire par la r gle de port e des identificateurs en Caml En effet tout identificateur est li la valeur qui l a d fini Cette liaison ne d pend pas du temps mais seulement de l endroit dans le programme o l identificateur est d fini c est pourquoi on parle aussi de port e textuelle ou lexicale Donnons un exemple de ce comportement nous d finissons la constante taille puis la fonction ajoute_ taille qui fait r f rence au nom taille puis nous red finissons le nom taille avec une autre valeur let taille 1 taille int 1 let ajoute_taille x x taille ajoute_taille int gt int lt fun gt let taille 2 taille int 2 328 Ex cution d un langage fonctionnel Le probl me est de savoir si la red finition de taille a modifi la fonction ajoute_taille ou bien si cette fonction ajoute toujours 1 son argument ajoute_taille O int 1 Caml suit bien la r gle de port e statique l identificat
422. nnus et on le renvoie Pour viter le bouclage on n essaye pas de calculer imm diatement les transitions issues du nouvel tat ce dernier est cr sans aucune transition sortante On se contente de le mettre dans la pile _remplir qui garde trace des tats incomplets dont il faudra d terminer les transitions plus tard Pour terminer la construction de l automate il faut d piler les tats incomplets d terminer les transitions sortantes en appelant d placements et fermeture_ens et R alisation de la commande grep 319 obtenir les tats de destination des transitions en appelant traduire Les appels traduire construisent parfois de nouveaux tats il faut donc r p ter ce processus jusqu ce que la pile _remplir soit vide La terminaison est assur e parce que le nombre d ensembles d tats possibles est fini si l automate initial a n tats il y a au plus 2 ensembles d tats diff rents consid rer On amorce le processus en appelant traduire sur la fermeture de l tat initial On obtient ainsi l tat initial de l automate d terministe Comme ses transitions n ont pas t calcul es la pile _remplir contient cet tat Le premier tour de la boucle while compl te cet tat comme d crit ci dessus Les tours suivants compl tent les tats cr s en cours de route Quand la pile est vide stack__pop d clenche l exception stack__Empty qui fait sortir de la boucle L automate d termin
423. nouvel tat et calcul des transitions issues de cet tat les tats sont cr s initialement sans transitions sortantes et on les compl te ult rieurement en ajoutant les transitions convenables Fichier determ ml let d terminise tat_initial let tats_connus hashtbl__new 51 and _ remplir stack__new in let traduire ens try hashtbl__find tats_connus ens contenu with Not_found gt let nouvel_ tat dterminal exists function n gt n terminal ens l ments dtransitions make_vect 256 Rejet in hashtbl__add tats_ connus ens contenu nouvel_ tat stack__push ens l ments nouvel _ tat _ remplir nouvel_ tat in let nouvel_ tat_initial traduire fermeture tat_initial in begin try while true do let liste nouvel _ tat stack__pop _ remplir in let d pl d placements liste in for i 0 to 255 do if not est_vide d pl i then nouvel_ tat dtransitions i lt Vers traduire fermeture_ens d pl i done done with stack__Empty gt end nouvel_ tat_initial Le c ur de la fonction de d terminisation est la fonction traduire qui prend en argument un ensemble d tats de l automate de d part et renvoie l tat correspondant de l automate d terministe Si l ensemble d tats a d j t rencontr on trouve dans la table tats_connus l tat associ Sinon on cr e un nouvel tat on l associe l ensemble d tats dans la table tats_co
424. ns ce qui signifie simplement que leur repr sentation comporte la liste exhaustive de leurs mon mes y compris ceux dont le coefficient est nul C est pourquoi nous appelons la fonction d impression de ces polyn mes imprime_polyn me_plein Cette fonction se contente d it rer la proc dure imprime_mon me sur tout le polyn me l aide d une boucle pour let imprime_polyn me_ plein p for i O to vect_length p 1 do imprime_mon me p i i done imprime_polyn me_plein int vect gt unit lt fun gt Le polyn me p x 2x 3 s imprime comme suit imprime_polyn me_ plein p 3 2x x 2 unit Addition des polyn mes L addition des polyn mes se fait mon me par mon me en ajoutant les coefficients des mon mes de m me degr 1 2 32 4 5xr 6 1 4 2 5 xr 3 6 x 5 7r 92 Math matiquement on a si P po pit poz gt px et Q qo qit got qnx alors max m n P Q po f qo f p f q z f p2 f q2 x f Pmax m n F gmax m n Cette d finition utilise la convention qu un coefficient de degr sup rieur au degr du polyn me est implicitement 0 On peut exprimer ces formules de fa on plus synth tique 44 Programmation imp rative en introduisant la notation math matique Y pour r sumer les sommes de termes si formule est une expression qui d pend de l entier i on note n X formule i pour formule 0 formule 1
425. nt gt t gt t Cette repr sentation apparemment redondante des ensembles d tats est bien adapt e l utilisation qu on en fait par la suite le champ l ments permet d it rer facilement sur tous les tats d un ensemble le champ contenu permet de tester efficacement l appartenance et l galit entre ensembles La primitive d galit struc turelle n est pas utilisable pour comparer des tats parce que la structure qui pend sous un tat est susceptible de contenir des cycles qui font boucler l galit Viennent ensuite les deux op rations de base de l algorithme de d terminisation d une part ajouter un tat ou ensemble d tats tous les tats qu on peut atteindre par des epsilon transitions ce qu on appelle prendre la fermeture d un tat ou ensem ble d tats d autre part d terminer les transitions possibles partir d un ensemble d tats Fichier determ ml let rec ajoute_fermeture tat ferm if appartient tat ferm then ferm else list_it ajoute_fermeture tat epsilon_transitions ajoute tat ferm let fermeture tat ajoute_fermeture tat vide D terminisation de l automate 317 let fermeture_ens ens list_it ajoute_fermeture ens l ments vide On appelle fermeture d un tat l ensemble des tats accessibles depuis cet tat en z ro une ou plusieurs epsilon transitions partir de l tat e on atteint e et aucun autre
426. nt indiscernables elles sont donc gales au sens logique En effet la logique ne distingue les propositions que par leur valeur de v rit pas par leur texte Deux propositions quivalentes ne sont donc pas logiquement diff rentes C est le m me ph nom ne qu en arithm tique o l on ne peut distinguer 1 1 de 2 bien que ces deux expressions ne soient pas syntaxiquement les m mes On sent bien que le calcul des tables de v rit est automatisable et qu un programme remplirait facilement les colonnes des tableaux notre place en calculant ainsi la valeur de v rit d une proposition complexe en fonction des propositions qui la composent Le programme engendrerait plus facilement que nous toutes les combinaisons possibles pour les diff rentes propositions l mentaires qui interviennent En effet cette combina toire augmente tr s vite pour 2 propositions P et Q nous avons 4 lignes dans le tableau mais pour 3 il en faudrait 8 pour 4 propositions 16 lignes et ainsi de suite pour n propositions 2 lignes Notre d monstrateur de th or mes fonctionne exactement selon ce principe 12 3 Le principe des d monstrations Notre d monstrateur est restreint aux th or mes de logique l mentaire Or un th or me n est rien d autre qu une proposition qui est toujours vraie Ceci conduit d ailleurs une petite difficult en math matiques on n crit jamais qu une proposition est vraie On se contente
427. nt pour les petits fichiers pour lesquels la taille de l arbre de Huffman n est pas n gligeable devant la taille du fichier produit en particulier le fichier compress peut devenir plus gros que le fichier d entr e Le deuxi me trait implique que l algorithme de Huffman n est pas adapt la compression au vol de donn es comme dans le cas des donn es qui transitent travers un modem et une ligne t l phonique Il existe une variante de l algorithme de Huffman qui ne pr sente pas ces deux inconv nients le codage de Huffman dynamique L id e est de changer d arbre de Huffman en cours de compression On part d un arbre de Huffman quilibr corre spondant au cas o tous les caract res ont la m me fr quence On lit les caract res sur l entr e en tenant jour les fr quences des caract res d j lus Chaque caract re est cod avec l arbre de Huffman courant puis l arbre est modifi pour qu il corresponde toujours aux fr quences des caract res d j lus Il n est pas obligatoire de reconstruire Pour aller plus loin 253 l arbre partir de z ro chaque nouveau caract re on arrive modifier l arbre de mani re locale et incr mentale Non seulement une deuxi me passe sur l entr e devient alors inutile mais il n est m me plus n cessaire de transmettre l arbre de Huffman au d compresseur la d compression part du m me arbre initial que la compression et le modifie
428. ntiques ces deux cas se traduisent par deux clauses du filtrage dont la partie expression est la m me Pour viter cette redite on joue sur le fait que l addition des polyn mes est commutative pour traiter le dernier cas par un appel r cursif la fonction ajoute_polyn me qui inverse les arguments p1 et p2 let rec ajoute_polyn mes pi p2 match pi p2 with Plein v Plein v gt Plein ajoute_polyn mes_pleins v v Creux 1 Creux 1 gt Creux ajoute_polyn mes_creux 1 1 Plein v Creux 1 gt Creux ajoute_polyn mes_creux plein_vers_creux v 1 Creux 1 Plein v gt ajoute_polyn mes p2 pi ajoute_polyn mes polyn me gt polyn me gt polyn me lt fun gt Cette derni re solution permet de ne pas dupliquer de code ce qui raccourcit l g rement le texte de la fonction et diminue la probabilit d introduire une erreur en ne modifi ant qu une des clauses lors de corrections ult rieures du programme En fait lorsque l expression renvoyer est compliqu e l appel r cursif s impose sans contestation pos sible Cependant cette solution pr sente l inconv nient de sugg rer que la fonction ajoute_polyn me est vraiment r cursive alors qu elle ne l est que pour des raisons administratives La multiplication n est pas plus compliqu e let rec multiplie_polyn mes pi p2 match pi p2 with Plein v Plein v gt Plein multiplie_polyn mes_pleins v v Cr
429. nvironnement avec x de type t et t de type t list La fonction type_motif ne pr sente pas de difficult s majeures Le seul cas qui introduit une contrainte de typage est le cas des motifs cons m m2 Dans ce cas il faut imposer que le type de m2 soit un type liste dont les l ments ont pour type celui du motif m1 Nous passons maintenant au typage des expressions Commentons bri vement les cas int ressants Pour une variable on va chercher son sch ma de types dans l environnement de typage et on sp cialise ce sch ma en rempla ant ses param tres par de nouvelles inconnues Pour une fonction on type successivement chacun des cas du filtrage qui la d finit Les types des motifs doivent tre gaux au type de l argument de la fonction Les types des expressions associ es doivent tre gaux au type du r sultat de la fonction Pour chaque cas la partie expression est typ e dans l environnement courant tendu par le typage du motif Pour une application le type de la partie fonction doit tre un type fl che t gt t2 avec t gal au type de la partie argument t2 nous donne alors le type du r sultat de l application Pour un let l essentiel du travail est fait par la fonction type_d f que nous expliquons juste apr s le code Les autres constructions se typent de mani re vidente L algorithme de synth se de types 347 Fichier synthese ml let rec type_exp env function Variable id gt
430. ode de r solution d un probl me nous appartienne en propre alors que nous d l guons aux machines la mise en uvre effective Un quilibre se cr e ainsi si la r flexion sur la m thode est hors de port e de la machine la gestion sans erreurs des passages de param tres et la reprise des appels r cursifs en suspens est un jeu d enfant pour la machine alors que nous serions incapables d une telle rigueur Rendons donc aux machines ce qui appartient aux machines Pour ceux que cela int resse la section suivante esquisse les fondements th oriques de la m thode qui explique pourquoi la proc dure hanoi marche effectivement Acces soirement il permet aussi de calculer la date laquelle les moines auront achev leur travail et donne donc une bonne id e de la date de la fin du monde Si tout cela ne vous pr occupe pas passez directement au chapitre suivant 2 4 Notions de complexit La complexit est l tude du nombre d op rations n cessaires l ach vement d un calcul Une analyse de complexit permet donc de se faire une id e du temps de cal cul n cessaire l ach vement d un programme en fonction de l argument qui lui est soumis En g n ral on compte le nombre d op rations l mentaires additions multi plications soustractions et divisions comparaisons de valeurs affectations d l ments de tableau et ou le nombre d appels de fonctions Par exemple la fonction successeur demande un
431. oie le tableau d instructions correspondant Fichier lecture mli open code value programme char stream gt instruction vect La lecture n est pas tr s complexe comprendre si ce n est qu on ne construit pas d arbre de syntaxe abstraite rien ne nous y oblige ici puisque nous n analyserons pas les programmes assembl s On se contente donc d assembler les instructions au vol d s leur lecture en laissant videmment non r solues les r f rences en avant C est la phase d extraction du code qui se chargera ensuite de cette r solution Pour l analyse lexicale nous r utilisons le g n rateur d analyseurs lexicaux lexuniv introduit au chapitre 12 convenablement param tr par la liste des mots cl s du langage d assemblage 272 Fichier lecture ml Simulation d un processeur open code open stockage open lexuniv let registre function lt MC r Entier nbr gt gt nbr lt MC sp gt gt sp lt MC ra gt gt ra let constante function lt Entier nbr gt gt nbr lt Ident nom_ tiq gt gt valeur_ tiquette nom_ tiq let op rande function lt registre r gt gt Reg r lt constante c gt gt Imm c let rec instruction function lt op ration op reg_op_reg ri o r2 gt gt assemble Op op ri o r2 lt test_invers test reg_op_reg r1 o r2 gt gt
432. olique d finie par fact au lieu de jmp 16 r 31 qui ferait r f rence au num ro absolu de l instruction braz r 1 fact_0 et au num ro du registre d di l adresse de retour En observant le code assembleur de la fonction factorielle on mesure la difficult qu il y crire un programme en assembleur plut t qu en Caml On comprend aussi bien mieux la diff rence entre style imp ratif et style fonctionnel l assembleur est par essence imp ratif car on ne travaille que par modification de registres Vous constatez aussi qu on doit tout g rer soi m me la main par exemple la r cursivit dans le cas de fact En revanche en assembleur toutes les ressources de la machine sont disponibles on peut tout faire malheureusement la contrepartie est qu il faut tout faire soi m me Stockage du code et gestion des tiquettes L assembleur 269 Fichier stockage mli open code exception Erreur of string value initialise unit gt unit and assemble instruction gt unit and poser_ tiquette string gt unit and valeur_ tiquette string gt int and extraire_code unit gt instruction vect Pour r soudre les tiquettes l assembleur est oblig de fonctionner en deux tapes dans la premi re tape il pose les tiquettes quand il les rencontre c est dire qu il note leur adresse absolue dans une table d association Lorsqu il rencontre nouveau l tiquette il la
433. on l aide de la r gle 7 en supprimant l argument 1 let tri_croissant tri_par_insertion function x gt function y gt x lt y tri_croissant _a list gt _a list lt fun gt On constate alors que la fonction tri_croissant n a plus le m me type et qu il ap para t dans ce type d tranges param tres de type _a Au contraire des param tres a qui signifient pour tout type a et d notent donc des types polymorphes les param tres _a signifient pour un certain type a qui sera d termin par les utilisations ult rieures de la fonction La fonction tri_croissant est donc monomorphe tri_croissant 3 2 1 int list 1 2 3 tri_croissant int list gt int list lt fun gt tri_croissant Bonjour Entr e interactive gt tri_croissant Bonjour D 0 on h Raodene Cette expression est de type string list mais est utilis e avec le type int list Le type inconnu _a est devenu le type int et la fonction tri_croissant est dor navant de type int gt int Ce ph nom ne est d la coexistence en Caml du polymorphisme et des structures mutables Il est expliqu en d tails la fin de ce livre page 363 lorsque nous aurons vu les m canismes qui permettent de le comprendre Retenons pour l instant que seule les fonctions et les constantes sont susceptibles d tre polymorphes les d finitions de 88 Listes fonctions obtenues par application partielle d
434. on qui n ont pas d effet visible puis rendre la main Bref notre Logo ne fera rien du tout tant qu on n y aura pas ajout du code pour lire des com mandes au clavier et les envoyer la fonction d ex cution Voici un aper u des fonctions d entr e sortie de la biblioth que Caml Light Pour afficher sur l cran on dispose des fonctions suivantes print _string s affiche la cha ne s print_char c affiche le caract re c print_int n affiche l entier n print _float f affiche le nombre flottant f print _newline affiche un retour la ligne Pour lire depuis le clavier on a read_line qui lit une ligne au clavier et renvoie la cha ne de caract res correspondante Pour lire et crire sur des fichiers au lieu d utiliser l cran et le clavier il faut utiliser des canaux d entr e type in_channel ou de sortie type out_channel L ouverture d un fichier en criture par la fonction open_out renvoie un canal de sortie sur le fichier indiqu let canal_ sortie open_out essai tmp canal_sortie out_channel lt abstr gt Pour crire sur un canal de sortie on dispose des fonctions output_string et output_char output_string canal_sortie Une ligne de texte n unit Enfin on ferme le canal de sortie avec close_out close_ out canal _sortie unit La lecture est tr s sym trique ouverture d un canal d entr e avec open_in lecture ligne ligne par input_l
435. on et retourner n factorielle n 1 La barre verticale introduit donc les cas et correspond un ou bien tandis que la fl che gt indique ce qu il faut calculer dans le cas correspondant L analyse de cas porte le nom technique de filtrage que nous emploierons d sormais Le filtrage est un trait extr mement puissant de Caml Il est int gr dans de nombreuses constructions du langage et tr s fr quemment employ dans les programmes Il arrive dans certains cas qu on n utilise pas l argument de la fonction pour calculer le r sultat let gal_un function 1 gt true x gt false gal un int gt bool lt fun gt Pour bien montrer que le nom x ne sert rien puisque sa valeur n est pas n cessaire pour retourner false on se sert d un symbole sp cial _ le soulign qui signifie dans tous les autres cas let est_un function 1 gt true _ gt false est_un int gt bool lt fun gt est_un 1 est_un O bool true bool false Nous abordons maintenant un probl me apparemment tr s difficile qu une fonction r cursive r sout sans difficult et avec une grande l gance 2 3 Les tours de Hanoi La l gende Le jeu des tours de Hanoi consiste en une plaquette de bois sur laquelle sont plant es trois tiges Sur ces tiges sont enfil s des disques de bois dont les diam tres sont tous diff rents La seule r gle du jeu est de n
436. on pour qu elle d finisse l id e de deux objets semblables La principale difficult pour expliciter ces propri t s provient de leur vidence m me nous y sommes tellement habitu s et elles paraissent tellement videntes que a va sans dire C est exactement le but de la logique que d crire noir sur blanc ces vidences La r flexivit signifie qu un objet est toujours gal lui m me x x La sym trie signifie que lorsqu un objet est gal un autre objet l autre objet est aussi gal au premier si x y alors y x La transitivit se traduit par deux objets gaux un m me troisi me sont gaux entre eux ou encore si x y et y z alors x z Le programme tablit pour nous ces trois propri t s de l quivalence logique gt gt gt P lt gt P Th or me pour toute proposition P P lt gt P gt gt gt P lt gt Q gt Q lt gt P Th or me pour toutes propositions Q P P lt gt Q gt Q lt gt P gt gt gt P lt gt Q et Q lt gt R gt P lt gt R Th or me pour toutes propositions R Q P P lt gt Q et Q lt gt R gt P lt gt R On utilise les deux th or mes suivants pour simplifier les circuits logiques Le pre mier permet d liminer deux connecteurs propositionnels gt gt gt P ou P et Q lt gt P Th or me pour toutes propositions Q P P ou P et Q lt gt P On supprime de m me un connecteur et une n
437. on y gt f x y curry Ca b gt c gt a gt b gt c lt fun gt Le type de la fonction curry est plus clair si l on r tablit les parenth ses omises par l imprimeur de types de Caml une fois n est pas coutume En effet a b gt c gt a gt b gt c selit aussi Ca be Pc gt Ca gt b gt c La fonctionnelle de d curryfication La fonctionnelle r ciproque uncurry n est pas plus complexe Elle prend en argu ment une fonction curryfi e g et rend en r sultat une fonction ayant un seul argument qui est une paire Ce r sultat est donc une valeur de la forme function x y gt let uncurry g function x y gt m me r sultat que g pour x et y Or puisque g est curryfi e deux arguments le m me r sultat que g pour x et y est g X y let uncurry g function x y gt g X y uncurry C a gt b gt c gt a b gt c lt fun gt De m me que pour curry le type de uncurry se lit plus facilement en r tablissant les parenth ses autour de a b gt c Composition de fonctions 73 Leurs compos es Intuitivement il est clair que les fonctionnelles curry et uncurry sont r ciproques l une de l autre partir d une fonction un argument de type paire curry renvoie une fonction deux arguments tandis que uncurry fait l inverse D ailleurs let id_ curry f compose cur
438. onc que le locuteur ne ment pas et dit la v rit C est donc que la phrase qu il nonce est vraie Dans les deux cas la phrase est la fois vraie et fausse ce n est donc pas une phrase math matique Une phrase acceptable est appel e proposition Une proposition peut donc tre soit vraie soit fausse Les valeurs vrai et faux sont appel es valeurs de v rit nous les noterons en abr g v et f Pour ceux qui penseraient tort que le paradoxe du menteur vient sans doute de confusions dues l impr cision du langage courant on peut prendre d autres exemples formul s dans un langage tout fait math matique cette fois ci Par exemple l ensemble de tous les ensembles qui ne sont pas l ments d eux m mes est l ment de lui m me Par le m me raisonnement que pour le paradoxe du menteur on voit que cet nonc est la fois vrai et faux Notez le lien avec les d finitions r cursives qui ne sont pas bien fond es nous avons d j soulign qu une phrase qui pr sente des autor f rences est susceptible de mener au non sens si l on n y prend pas garde section 2 1 Les connecteurs propositionnels Les op rations que nous allons d finir sur les propositions sont appel es connecteurs propositionnels puisqu elles relient des propositions pour fabriquer d autres proposi tions Nous commen ons par le contraire d une proposition qu on appelle aussi sa n gation C est
439. ondante sur les entiers suffix par un point 1 0 2 0 3 14159 gt 18 9 2 718 bool true En plus des quatre op rations on dispose des fonctions transcendantes habituelles l exponentielle exp la fonction puissance power et les fonctions trigonom triques cosinus cos sinus sin tangente tan et leurs r ciproques logarithme 1og racine carr e sqrt arccosinus acos arcsinus asin et arctangente atan On dispose aussi de conversions entre entiers et flottants int_of_float et float_of_int sqrt 2 0 float 1 41421356237 Nous d finissons la fonction round pour arrondir les coordonn es du crayon l entier le plus proche let round x if x gt 0 0 then int_of_float x 0 5 else int_of_float x 0 5 round float gt int lt fun gt 8 4 Le crayon lectronique Le comportement du crayon lectronique est le suivant e Le crayon trace dans une direction qu on peut faire varier la demande et que nous nommerons la vis e du crayon e Il se d place d une distance qu on lui indique dans la direction de sa vis e actuelle 150 Graphisme e En avan ant le crayon ne laisse pas de trace s il est lev et trace un trait s il est baiss Pour g rer le crayon il nous faut donc tenir jour et faire voluer son tat courant ses coordonn es son angle de vis e et le mode de trac crayon lev ou non Cet tat est d crit par un type
440. onjour prix_ _payer 40 message nBonjour je m appelle Cam lia n nJe suis l pour vous aider r soudre vos probl mes psychologiques nTerminez en me disant Au revoir n nAllons y Parlez moi de vous n bonjour unit gt unit lt fun gt let au_revoir message nLe r sultat de mes observations n message au_choix_dans salutations message nAu revoir n print_string Vous me devez print_int prix_ _payer message euros Ch que l ordre de Cam lia Merci au_revoir unit gt unit lt fun gt Pour lire la r ponse du patient on utilise la fonction pr d finie read_line qui lit une ligne tap e au clavier De mani re tr s r aliste chaque change entre le patient et Cam lia accro t la note de la consultation let coute _le_ patient prix_ _payer lprix_ _ payer 2 print_string gt gt read_line coute_le_patient unit gt string lt fun gt Pour simplifier le travail de recherche des phrases courtes on utilise une fonction qui re conna t les phrases synonymes Par exemple la phrase comment est assimil e quoi De m me bien s r oui et bien s r que oui sont assimil es oui let rec synonyme_de_phrase function comment gt quoi bien sur gt oui bien sur que suite gt synonyme_de_phrase suite evidemment certainement gt oui pas du tout _
441. onnues map fun var gt var nouvelle_inconnue params in let rec copie ty match valeur_de ty with Variable var as ty gt try assq var nouvelles_inconnues with Not_found gt ty Terme constr arguments gt Terme constr map_vect copie arguments in copie sch ma corps 18 6 Impression des types Il nous reste crire les fonctions d impression des types C est un peu long mais sans r elle difficult La seule astuce consiste produire de jolis noms pour les variables de type a b Nous avons galement simplifi le code en supposant que les constructeurs de types ont au plus deux arguments et que ceux qui ont deux arguments se notent de mani re infixe comme gt et Ce n est pas vrai en g n ral mais c est le cas en mini Caml Fichier types ml let noms_des_variables ref variable _de_type string list and compteur_de_variables ref O let imprime_var var print _string try print_string assq var noms_des_variables with Not_found gt let nom make_string 1 char_of_int int_of_char a compteur_de_variables in incr compteur_de_variables noms_des_variables var nom noms_des_variables print_string nom let rec imprime ty 358 Un synth tiseur de types match valeur_de ty with Variable var gt imprime_var var Terme constructeur arguments gt match vect_length arguments with O gt print_string construc
442. ons Une proposition comporte donc parfois des variables libres Mais pour calculer la valeur de v rit d une proposition il faut absolument conna tre la valeur de ses vari ables libres Comme d habitude notre machine ne peut calculer qu en connaissant la valeur de toutes les entit s qui interviennent dans l expression calculer cf exemple x x gt de la section 1 3 Nous utiliserons donc des liaisons qui associent une valeur bool enne toute variable libre de la proposition tudi e tant donn un ensemble de liaisons de variables l valuation d une proposition s op re en traduisant simplement les connecteurs de la logique l aide des op rateurs logiques de Caml not amp amp Fichier prop ml let rec value _dans liaisons function Vrai gt true Faux gt false Non p gt not value _ dans liaisons p Et p q gt value_dans liaisons p amp amp value_dans liaisons q Ou p q gt value _ dans liaisons p value_dans liaisons q Implique p q gt not value_dans liaisons p value_dans liaisons q quivalent p q gt value_dans liaisons p value_dans liaisons q Variable v gt assoc v liaisons La fonction value_dans oblige donc faire la relation entre les connecteurs de la logique et les op rateurs logiques de Caml Il faudrait d montrer en analysant tous les cas possibles des propositions arguments des co
443. ons valuer nous m mes les op rations sur les nombres C est tr s simple lorsque les deux nombres sont des entiers il suffit d appeler la primitive correspondante de Caml sur les entiers sinon on transforme les deux nombres en flottants et l on appelle la primitive correspondante sur les flottants cette fois let ajoute_nombres function Entier i Entier j gt Entier i j ni n2 gt Flottant flottant ni flottant n2 and soustrais_nombres function Entier i Entier j gt Entier i j ni n2 gt Flottant flottant ni flottant n2 and multiplie_nombres function Entier i Entier j gt Entier i j ni n2 gt Flottant flottant ni flottant n2 and divise_nombres function Entier i Entier j gt Entier i j ni n2 gt Flottant flottant ni flottant n2 and compare_nombres function Entier i Entier j gt i gt j ni n2 gt flottant ni gt flottant n2 ajoute_nombres nombre nombre gt nombre lt fun gt soustrais_nombres nombre nombre gt nombre lt fun gt multiplie_ nombres nombre nombre gt nombre lt fun gt divise_nombres nombre nombre gt nombre lt fun gt 170 Syntaxe abstraite syntaxe concr te compare_nombres nombre nombre gt bool lt fun gt L valuateur des expressions lui m me est un peu plus complexe En effet il a un ar gument suppl mentaire env qui sert retrouver la valeu
444. ons l expliquer puis l utiliser pour d montrer des propri t s de la fonction hanoi Le principe de r currence s nonce informellement ainsi si une certaine propri t sur les nombres entiers est vraie pour 0 et si la propri t est vraie pour le successeur d un nombre d s qu elle est vraie pour ce nombre alors cette propri t est vraie pour tous les nombres Formellement soit P n une propri t qui d pend d un entier n Si les phrases suivantes sont vraies 1 P 0 est vraie 2 si P n est vraie alors P n 1 est vraie alors P n est vraie pour tout n Ce principe est en fait vident les deux propri t s demand es par le principe de r currence permettent facilement de d montrer la propri t P pour toute valeur enti re Par exemple supposons que P v rifie les deux propri t s et qu on veuille d montrer que P est vraie pour 2 Puisque P est vraie pour 0 elle est vraie pour son successeur 1 Mais puisque P est vraie pour 1 elle est vraie pour son successeur donc elle est vraie pour 2 Il est clair que ce raisonnement se poursuit sans probl me pour tout nombre entier fix l avance C est ce principe que nous avons utilis pour r soudre le probl me des tours de Hanoi 1 nous avons montr que nous savions le r soudre pour 0 disque 2 nous avons montr qu en sachant le r soudre pour n 1 disques nous savions le r soudre pour n disques Ces deux cas correspondent exactement
445. op rations utilis es ici sont infixes Pour crire la fonctionnelle nous utilisons un argument fonctionnel normal donc pr fixe Il faut donc relire le code des exemples avec des op rations pr fixes par exemple pour somme l op ration pr fixe correspondant est la fonction pr d finie add_int c est dire function x gt function y gt x y Notre fonctionnelle s crit maintenant tr s facilement let rec it rateur_sur_listes f b function D gt b x 1 gt f x it rateur_sur_listes f b 1 it rateur_sur_listes a gt b gt b gt b gt a list gt b lt fun gt Pour d finir somme en utilisant l it rateur on crira simplement let somme 1 it rateur_sur_listes add_int O 1 somme int list gt int lt fun gt Fonctionnelles complexes sur les listes 93 somme 1 2 3 l int 6 D autres programmes ressortissent du m me sch ma Consid rons par exemple la fonc tion qui calcule la longueur d une liste qui est pr d finie en Caml sous le nom de list_length Elle s crit sans difficult let rec list_length function O gt 0 x 1 gt 1 list_length l list_length a list gt int lt fun gt C est encore le m me sch ma l l ment de base est 0 l op ration est l addition de 1 On peut donc crire let list_length 1 it rateur_sur_listes function x gt function y gt 1 y O l list_length
446. opri t sur un type produit deux composantes seulement et pour simplifier encore supposons que ce soit le type int int Pour prouver une propri t P qui d pend d une paire d entiers m n on utilisera par exemple le principe de r currence suivant Si P 0 0 est vraie et d s que P m n est vraie alors P m 1 n et P m n 1 sont vraies alors P est vraie pour tous m et n Ce principe se d montre facilement partir du principe de base et se g n ralise sans difficult un nombre quelconque de variables Cette extension du principe de r currence aux structures de donn es se nomme tout naturellement la r currence structurelle C est le principal moyen de d monstration la disposition de l informaticien Il est heureux qu il soit si simple appr hender Le docteur O l intelligence naturelle vient au secours de la b tise artificielle N VOUS INITIE ICI au maniement des exceptions des listes d association et des entr es sorties l mentaires de Caml Par ailleurs on impl mente un programme qui essaye de se faire passer pour un psychanalyste 7 1 Vue d ensemble Notre psychanalyste lectronique s appelle Cam lia C est un programme inter actif qui pose des questions son patient et r agit ses r ponses en imprimant un message au terminal La strat gie du programme repose donc sur l examen des phrases entr es par le patient Une fois la phrase examin e le programme chois
447. or il faut sans conteste employer une boucle les indices sont en t te de boucle il n y a pas besoin de fonction auxiliaire c est donc bien plus clair En ce qui concerne l efficacit il n est pas clair que l une des versions 52 Programmation imp rative soit meilleure que l autre tout d pend du compilateur Remarquez en particulier que les versions r cursives ne font que des appels r cursifs terminaux c est dire plac s en fin de fonction Ce genre d appels r cursifs est tr s bien optimis par les compilateurs Caml qui les transforment automatiquement en boucles Le processus de r criture d une fonction r cursive l aide de boucles que nous avons vu ici sur des exemples s appelle la d r cursivation Cette op ration est sou vent difficile essayez par exemple de d r cursiver la fonction hanoi contrario les fonctions r cursives permettent d crire facilement les boucles les plus complexes en particulier lorsque la boucle comporte plusieurs sorties possibles ou lorsque l indice ne varie pas de fa on uniforme ou simplement lorsqu il faut retourner une valeur signi ficative diff rente de la fin de la boucle Cependant la r cursivit ne se limite certainement pas coder des boucles c est un outil extr mement puissant comme vous l avez constat avec le jeu de Hano Nous en verrons encore beaucoup d exemples non triviaux dans la suite 3 9 R gle d extensionnalit
448. ordres graphiques et une fonction ex cute_ordre qui les ex cutera La fonction r p te prendra alors en argument une liste de valeurs du type ordre qu elle pourra ex cuter autant de fois que n cessaire en utilisant la fonction ex cute_ordre Nous r solvons de la m me mani re le probl me des nombres en d finissant un type nombre qui regroupe des valeurs flottantes et enti res type nombre Entier of int Flottant of float Le type nombre est d fini Les op rations de base du crayon n acceptant que des arguments flottants il nous faut une fonction traduisant les nombres valeurs du type nombre en valeurs du type float let flottant function Entier i gt float_of_int i Flottant f gt f flottant nombre gt float lt fun gt 158 Syntaxe abstraite syntaxe concr te 9 3 L valuation des ordres du langage graphique Nous d finissons maintenant le type des ordres graphiques Constructeur Ordre graphique Constructeur Ordre graphique repr sent repr sent Av avance Re recule Td tourne droite Tg tourne gauche Lc l ve le crayon Bc baisse le crayon Ve vide l cran Rep r p tition d une liste d ordres type ordre Av of nombre Re of nombre Td of nombre Tg of nombre Le Bc Ve Rep of int ordre list Le type ordre est d fini La fonction d valuation ex cute les ordres graphiques en utilisant les fonctions graphiques du
449. os_in entr e 274 Simulation d un processeur prerr_endline 1 stockage__Erreur message gt prerr_string Erreur d assemblage prerr_endline message 1 gt raise exc La fonction principale se contente d analyser ses arguments puis si tout va bien elle appelle la fonction assemble_fichier pr c dente Fichier asm ml exception Mauvais_arguments if sys__interactive then else try if vect_length sys__command_line lt gt 3 then raise Mauvais_arguments exit assemble_fichier sys__command_line 1 sys__command_line 2 with Mauvais_arguments gt prerr_endline Usage pico_asm lt fichier assembleur gt lt fichier de code gt exit 2 sys__Sys_error message gt prerr_string Erreur du syst me exit 2 prerr_endline message Comme pour la commande pico_run on compile puis assemble les modules de l assembleur pour produire la commande pico_asm camlc c stockage mli camlc c stockage ml camlc c lexuniv mli camlc c lexuniv ml camlc c lecture mli camlc c lecture ml camlc c asm ml camlc o pico_asm code zo stockage zo lexuniv zo lecture zo asm zo Exemple Nous ex cutons la fonction factorielle l aide de la pico machine Il nous faut as sembler le fichier fact asm avec la commande pico_asm puis charger les instructions en m moire programme et lancer la pico machine avec la commande pico_run pico_asm fact asm fact o pico_run f
450. osition de fonctions 70 5 Listes 75 5 1 Pr sentation 75 5 2 Programmation assist e par filtrage 77 5 3 Tri par insertion 78 5 4 Fonctionnelles simples sur les listes 81 5 5 Les polyn mes creux 83 5 6 Filtrage explicite 84 5 7 Op rations sur les polyn mes creux 85 5 8 Animation des tours de Hanoi 88 5 9 Fonctionnelles complexes sur les listes 91 5 10 Efficacit des fonctions sur les listes tude de cas 98 5 11 Listes et r currence 103 5 12 la recherche de l it rateur unique 105 6 Les structures de donn es 109 6 1 Polyn mes pleins et polyn mes creux 109 6 2 Types sommes labor s 113 6 3 Les types somme 116 6 4 Les types produit 116 6 5 M lange de types somme et types produit 118 6 6 Structures de donn es mutables 118 6 7 Structures de donn es et filtrage 120 6 8 Structures de donn es et r currence 122 7 Le docteur 125 7 1 Vue d ensemble 125 7 2 Les exceptions 126 7 3 Fonctions de recherche dans les listes 130 7 4 Traitements de cha nes de caract res 133 7 5 Cam lia 135 7 6 Dialogue avec l utilisateur 140 7 7 Exemple de session 143 7 8 Pour aller plus loin 144 8 Graphisme 147 8 1 Fractales 147 8 2 Le graphisme de Caml 148 8 3 Les nombres en repr sentation flottante 149 8 4 Le crayon lectronique 149 8 5 Premiers dessins 152 8 6 Le flocon de von Koch 154 9 Syntaxe abstraite syntaxe concr te 155 9 1 Pr sentation 155 9 2 Le retard l valuation 156 9 3 9 4 9 5 9 6 9 7 L valuation des ord
451. oue Elle envisage donc tous les cas possibles de deux valeurs du type type_simple Les deux premiers cas du filtrage concernent le cas d une variable libre unifier avec un type et son cas sym trique Le dernier cas correspond deux types construits Lorsqu un des types est une variable il suffit de modifier physiquement cette variable pour la rendre gale l autre type Comme expliqu ci dessus il faut cependant effectuer le test d occurrence et remettre jour les niveaux des variables dans le type Lorsque les deux types sont des types construits de deux choses l une ou bien leurs constructeurs sont gaux et alors il suffit d unifier r cursivement leurs arguments pour rendre les deux types gaux ou bien leurs constructeurs sont diff rents auquel cas l quation n a pas de solutions et l exception Conflit est d clench e Il reste un dernier cas qui est intercept au tout d but de la fonction unifie lorsque les deux types sont d j gaux et tout particuli rement lorsqu ils repr sentent la m me variable il n y a rien faire Pour d tecter cette situation nous prenons les valeurs des deux types en supprimant les variables connues Si les valeurs sont physiquement gales les deux types sont gaux et l unification s arr te aussit t Fichier types ml let rec unifie ty1 ty2 let valeuri valeur _de tyl and valeur2 valeur_de ty2 in if valeuri valeur then else mat
452. ous allons voir ce m canisme l uvre dans la r solution du syst me pr c dent en supposant simplement que les deux quations sont pr sent es dans l ordre inverse On commence donc par prendre en compte l quation t2 t int et t reste une inconnue t devient t int Inconnue Inconnue Inconnue gt l il int Inconnue Maintenant la prise en compte de l quation t int modifie automatiquement le type t int ce qui a l effet suivant t devient int or TR Inconnue l int int l int Inconnue int Finalement gr ce au ph nom ne de partage la r solution produit exactement le m me r sultat quel que soit l ordre dans lequel on r sout les quations Repr sentation des types 351 t devient int Inconnue y int 7 int int Inconnue int En r sum la r solution du syst me produit toujours l effet suivant t devient int et t devient t int gt Inconnue Inconnue int int int Modification physique des valeurs point es Voici un exemple plus difficile o les modifications physiques doivent s op rer sur les valeurs point es par les variables et non sur les variables elles m mes t t ti b t int La prise en compte de l quation t t2 modifie physiquement la variable t1 qui pointe maintenant vers t Cet
453. ous r veillent ils la Et c est tout ce que vous vouliez me nuit dire Avez vous des insomnies Est ce pour cela que vous vous tes Faites vous beaucoup de cauchemars adress moi l Faites vous souvent des r ves tranges fatigue Que pensez vous de l hypnose l La fatigue n est pas une maladie anxieux anxieuse Quand on est fatigu ne faut il pas se I L anxi t est une vraie maladie reposer Les anxieux ont souvent des probl mes avec Je suis une machine je ne connais pas la leur entourage L avez vous remarqu fatigue L anxi t est une vraie souffrance Ah fr les humains qui connaissez la non fatigue stupide idiot Que pensez vous de la fatigue en g n ral Pensez vous que ce soit un crime d tre Pourquoi pensez vous que a vaut la peine stupide de se fatiguer J ai d excellents amis qui sont stupides Les gens fatigu s le sont souvent de leur aussi fait non La sottise est la chose du monde la mieux tu vous toi partag e I Ne parlons pas de moi Ne soyez pas stupide non plus Parlons de vous c est plus important Vous m me n tes vous pas stupide Si on parlait de vous quelquefois Moi je ne suis qu une machine Ne pensez vous pas que c est quelquefois Moi utile d tre stupide Excusez moi femme Ne m en veuillez pas
454. pairs on repr sente l entier Caml n par le mot 2n 1 dans la machine On compile alors sans difficult s les primitives arithm tiques en tenant compte de ce codage l addition de deux entiers consiste additionner leurs codes et soustraire 1 au r sultat par exemple Le prix de ce codage est un l ger ralentissement des op rations arithm tiques et l impossibilit d obtenir tout l intervalle des entiers repr sentables par un mot machine on perd un bit La compilation du polymorphisme Tout comme la r cup ration automatique de m moire le polymorphisme impose galement des contraintes sur la repr sentation des donn es Caml dans la machine Les fonctions polymorphes sont appliqu es des donn es de types diff rents sur lesquelles ces fonctions op rent de fa on uniforme Le m me code machine doit donc op rer uni form ment sur des donn es de tous les types des entiers aux structures de donn es les plus complexes Ceci n est possible que si tous les types de donn es partagent un format commun de repr sentation en particulier si toutes les repr sentations ont la m me taille En g n ral on choisit une taille d un mot m moire Les objets qui occu pent naturellement plus d un mot nombres flottants n uplets etc sont alors allou s La compilation de Caml 369 en m moire et manipul s par l interm diaire d un pointeur Cette approche simple se pr te parfaitement au polymorphisme au prix d une ce
455. pas tre employ comme identificateur Par exemple en Caml il est impossible d employer if comme un nom de variable une phrase comme let if 3 est syntaxiquement incorrecte Le mot cl if est donc r serv en Caml ainsi que tous les autres mots cl s En revanche le mini Logo du chapitre 9 n a pas de mots cl s r serv s on crit sans probl me la proc dure pour carr r p te r p te 4 av r p te td 90 en utilisant ainsi l identificateur r p te la fois comme mot cl et comme nom de variable Dans le cas de mini Logo ce n est pas catastrophique puisque les variables sont explicitement diff renci es par le symbole qui les pr c de Mais un langage comme PL 1 n a pas cette convention et pourtant ne r serve aucun mot cl autorisant donc des phrases comme if then else then else if else then if Comme on le voit sur cet exemple ne pas r server les mots cl s peut conduire des programmes vraiment illisibles Nous allons donc r server les mots cl s de la syntaxe concr te des propositions Les changements apporter l analyseur lexical sont min imes lorsqu on a reconnu une suite de caract res qui a la forme d un identificateur il faut tester si cette suite de caract res est un mot cl ou non et renvoyer des lex mes diff rents selon le cas Par exemple ayant lu truc qui n est pas un mot cl on ren verra le lex me Ident truc mais si on lit ou on renverra le lex me
456. phrase vraie L hypoth se P est vraie et Q est fausse se traduit simplement par P et non Q Sous cette hypoth se peut on d montrer que P et Q est vraie gt gt gt P et non Q gt P et Q P et non Q gt P et Q n est pas un th or me car la proposition est fausse quand P est vraie Q est fausse Non la d duction est erron e En revanche le contraire est exact gt gt gt P et non Q gt non P et Q Th or me pour toutes propositions Q P P et non Q gt non P et Q Examinons maintenant la validit du raisonnement complexe Exemples de th or mes 225 Puisque P est vraie et que Q est fausse P n est donc pas une condition n cessaire pour que Q soit vraie La premi re ligne ne pose pas de probl me de traduction Le raisonnement puisque R donc S se traduit ais ment c est une autre fa on d exprimer que l implication R S est vraie Le raisonnement se traduit donc par P et non Q gt En revanche que signifie condition n cessaire P est une condition n cessaire pour Q si d s que Q est vraie alors P est elle aussi vraie Autrement dit si Q est vraie P est n cessairement vraie Cela signifie que l on a Q P La phrase P n est pas une condition n cessaire pour que Q soit vraie signifie donc simplement non Q P En mettant les morceaux ensemble on obtient gt gt gt P et non Q gt non Q gt P P et non Q gt non Q gt P
457. physique est not e Ainsi quand le test var var rend vrai cela indique que var et var sont en fait la m me variable dans ce cas on d clenche l exception Circularit avec pour arguments la variable et le type qu on voulait lui affecter L unification 355 Mise jour des niveaux des variables Chaque variable porte donc un niveau qui indique dans quelle d finition elle a t cr e Plus le niveau est lev plus la variable a t introduite r cemment Lorsqu on affecte une variable v par un type t il faut pr server cette information En particulier si le type t contient des variables de niveau plus lev que v il faut abaisser le niveau de ces variables au niveau de v Tout doit se passer comme si au lieu d avoir introduit une variable une certaine date puis d termin sa valeur par r solution de contraintes on avait devin la valeur correcte au moment de l introduction de la variable La fonction rectifie_niveaux garantit cette propri t Fichier types ml let rec rectifie_ niveaux niveau_max ty match valeur_de ty with Variable var gt if var niveau gt niveau_max then var niveau lt niveau_max Terme constructeur arguments gt do_vect rectifie_niveaux niveau_max arguments Le moteur de la r solution La fonction qui unifie deux types proc de par filtrage sur ces types et ne rend pas de valeur elle fait les affectations n cessaires ou bien elle ch
458. ple si on cherche un num ro se terminant par 7 ce qui fait que la recherche est quasi imm diate Dans tous les cas on restreint nettement l espace de recherche Il est facile de construire les sous ensembles automatiquement On part d une table o tous les sous ensembles sont vides let table _des_sous_ensembles make_vect 10 int string list vect 234 D monstration de propositions Puis on range chaque paire cl valeur m moriser dans le sous ensemble correspon dant la valeur de hachage de la cl let ajoute_une_cl cl valeur as cl _valeur let num ro_du_sous_ensemble hache cl in table_des_sous_ensembles num ro_du_sous_ensemble lt cl _valeur table_des_sous_ensembles num ro_du_sous_ensemble ajoute_une_cl int string gt unit lt fun gt do_list ajoute_une_cl liste_d association unit table _des_sous_ensembles int string list vect 11139635570 Nelly 139635511 standard 11 police 139635202 Xavier 3613 T l tel 1 7234864 Xavier 3615 T l tel 3 16 pompiers 139635198 Pierre 71 Le hachage n est pas restreint aux cl s de type entier On peut l appliquer n importe quel type de cl s pourvu qu on sache associer rapidement un entier une cl On d finit alors la fonction de hachage comme tant l entier associ la cl modulo la taille de la table de hachage La
459. plusieurs types diff rents Le polymorphisme n est pas l apanage des fonctions certaines valeurs non fonc tionnelles peuvent aussi tre utilis es avec plusieurs formes c est dire plusieurs types Les exemples se trouvent du c t des structures de donn es comme les tableaux et les listes clairement un tableau de nombres entiers ne pourra pas tre employ avec un autre type mais vous admettrez facilement que le tableau vide le tableau z ro l ment peut tre vu comme un tableau d entiers aussi bien que comme un tableau 58 Fonctionnelles et polymorphisme de cha nes Nous allons nous int resser d abord aux fonctions polymorphes parce que c est dans le domaine des fonctions que cette notion est la plus naturelle et la plus facile appr hender Pour exprimer le polymorphisme dans les expressions de types nous avons besoin d une notion de types qui puissent remplacer plusieurs types diff rents ce sont les param tres de type qu on distingue syntaxiquement des types ordinaires en les faisant pr c der d une apostrophe Par exemple a est un param tre de type nomm a Le polymorphisme de Caml est techniquement qualifi de param trique Intuitive ment cela signifie que ce polymorphisme fonctionne en tout ou rien La signification d un param tre de type est de remplacer n importe quel autre type et non pas un certain nombre d autres types On n aura donc pas de programmes Caml unique
460. polyn me p if p est un polyn me plein then imprime_polyn me_ plein p 110 Les structures de donn es else imprime_polyn me_creux p C est effectivement la bonne id e mais il faut la raffiner un peu outre qu on ne voit pas comment impl menter le pr dicat est un polyn me plein il se pose galement un probl me de typage pour l argument p de imprime_polyn me est ce une liste comme le sugg re l appel de fonction imprime _ polyn me _creux p ou un tableau pour pouvoir tre pass en argument imprime_polyn me_plein On obtiendrait forc ment une erreur de typage Par exemple en supposant que est un polyn me plein renvoie toujours la valeur true let imprime_polyn me p if true then imprime_ polyn me _ plein p else imprime_polyn me_creux p Entr e interactive gt else imprime_polyn me_creux p S 2 Cette expression est de type int vect mais est utilis e avec le type int int list Il faut donc m langer les polyn mes creux et pleins au sein d un m me type qui les comprenne tous les deux Le type polyn me On d finit donc un nouveau type polyn me qui tablit explicitement le m lange il indique qu il comprend deux cas possibles le cas des polyn mes pleins qui seront des tableaux d entiers et le cas des polyn mes creux qui seront des listes de paires d entiers type polyn me Plein of int vect Creux of int int list Le type polyn me est d
461. q hashtbl__new 17 _r soudre let initialise asm pc lt 0 asm code lt make_vect 100 Stop hashtbl__clear asm table_ tiq asm _r soudre lt let d code_adresse adr adr taille_du_mot 270 Simulation d un processeur let assemble instruction if asm pc gt vect_length asm code then begin let nouveau_code make_vect 2 vect_length asm code Stop in blit_vect asm code 0 nouveau_code 0 vect_length asm code asm code lt nouveau_code end asm code d code_adresse asm pc lt instruction asm pc lt asm pc taille _du_mot let d finir_ tiquette nom_ tiq val_ tiq try hashtbl__find asm table_ tiq nom_ tiq raise Erreur tiquette nom_ tiq with Not_found gt hashtbl__add asm table_ tiq nom_ tiq val_ tiq red finie let poser_ tiquette nom_ tiq d finir_ tiquette nom_ tiq asm pc let valeur_ tiquette nom_ tiq try hashtbl__find asm table_ tiq nom_ tiq with Not_found gt asm _r soudre lt asm pc nom_ tiq asm _r soudre 0 La fonction assemble surveille le compteur ordinal virtuel s il d borde de la m moire programme virtuelle alors on remplace le tableau initial par un nouveau tableau deux fois plus long dans lequel on recopie les instructions d j assembl es et l on continue normalement La recopie est effectu e par la fonction pr d finie blit_vect qui est l analogue pour les tableaux de la fon
462. que l argument de phi en supposant que son type n tant plus directement celui de identit deviendrait polymorphe il s agit ici d une 7 expansion let phi identit let id x identit x in id 1 id oui Entr e interactive gt id 1 id oui A Cette expression est de type string mais est utilis e avec le type int Encore une fois id reste monomorphe car le synth tiseur de type n a pas g n ralis le type de id qui provenait d une sp cialisation du type de identit l argument de la fonction phi les inconnues cr es pour construire le type de id sont aussi vieilles que le type dont elles proviennent dans l algorithme de typage la vieillesse est h r ditaire R p tons cette r gle fondamentale du typage de Caml seul le let donne du poly morphisme Cela a des cons quences tranges pour les fonctions anonymes elles ne sont jamais polymorphes C est pourquoi des phrases s mantiquement quivalentes sont sus ceptibles d avoir des types diff rents On sait par exemple que function x gt e2 e1 produit le m me r sultat que let x e1 in e2 C est parfaitement vrai en ce qui concerne l ex cution C est faux en ce qui concerne le typage puisque l identificateur x n est jamais polymorphe dans la version avec function tandis que la version avec let l y autorise La construction match with met en vidence le m me ph nom ne 344 Un synth tiseur de types
463. quel ordre sans changer le r sultat x y y zx L associativit concerne les parenth ses elle indique simplement que la place des parenth ses ne change pas le r sultat d une addition ce qu on exprime par une formule qui montre que d placer les parenth ses ne modifie pas le r sultat du calcul x y 2 x y 2 Le ou et le et v rifient ces propri t s gt gt gt P ou Q lt gt Q ou P Th or me pour toutes propositions Q P P ou Q lt gt Q ou P gt gt gt P ou Q ou R lt gt P ou Q ou R Th or me pour toutes propositions R Q P P ou Q ou R lt gt P ou Q ou R L implication est elle aussi associative et commutative gt gt gt P gt Q lt gt Q gt P P gt Q lt gt Q gt P n est pas un th or me car la proposition est fausse quand P est fausse Q est vraie gt gt gt P gt Q gt R lt gt P gt Q gt R P gt Q gt R lt gt P gt Q gt R n est pas un th or me car la proposition est fausse quand P est fausse Q est vraie R est fausse Une propri t int ressante une combinaison de et et de ou se comporte comme la multiplication et l addition on la d veloppe de fa on analogue Il est bien connu que la multiplication est distributive par rapport l addition ce qui per met d crire x x y 2 x x y x x z Notre programme prouve que le et est distributif pa
464. quer le comportement d une table de hachage Une table de hachage est une table d association physiquement modifiable elle enregistre des associations de certaines cl s avec certaines donn es on entre de nouvelles associations ou l on en retire d anciennes en modifiant physiquement la table Voici une partie de l interface du module hashtb1 de la biblioth que standard qui impl mente les tables de hachage type a b t value new int gt a b t 230 D monstration de propositions and add a b t gt a gt b gt unit and find a b t gt a gt b Le type a b hashtbl__t est le type des tables de hachage associant des cl s de type a avec des donn es de type b La fonction hashtbl__new renvoie une nou velle table de hachage initialement vide c est dire ne contenant aucune liaison Le param tre entier de hashtbl__new est une indication de la taille de la table nous verrons son r le dans la prochaine section La fonction hashtbl__find effectue une recherche dans une table de hachage hashtbl__find t c renvoie la donn e laquelle la cl c est li e dans la table t ou d clenche l exception Not_found si la cl c n est pas li e La fonction hashtbl__add enregistre une liaison dans une table de hachage hashtbl__add t c d place dans la table t une liaison de la cl c la donn e d Si la cl c tait d j li e une donn e la nouvelle l
465. qui concerne l introspection de Caml Nous avons donn une s mantique interpr teur pour mini Caml Nous l avons fait des fins p dagogiques mais ce n est pas une m thode r aliste d impl mentation de Caml tous les syst mes Caml reposent sur des compilateurs Cela peut surprendre dans la mesure o tous les syst mes Caml proposent aussi une boucle d interaction l utilisateur Or il est clair qu un interpr te est plus adapt l valuation interactive puisqu il calcule directement la s mantique du programme alors qu un compilateur s pare nettement la production du code compil de son ex cution rendant apparemment impossible l obtention imm diate du r sultat du programme Cependant tous les syst mes Caml disposent d une boucle d interaction sans interpr te uniquement bas e sur un compilateur chaque phrase entr e par l utilisateur est aussit t compil e puis le code produit est ex cut la vol e Cette m thode est techniquement plus difficile que l interpr tation mais elle of fre de grands avantages lorsqu un langage est valu par deux m thodes diff rentes interpr tation et compilation il se pose imm diatement des probl mes de coh rence entre ces deux m thodes Il faut en effet prouver que dans tous les cas les r sultats pro duits par l interpr te et par le compilateur sont les m mes En ce qui concerne Caml cette propri t est assur e de facto puisqu il n y a
466. quivalence et qu on note d habitude amp Intuitivement deux propositions sont quivalentes quand elles sont tou jours vraies ou fausses en m me temps Par exemple si P amp Q est vra e on d duit imm diatement la valeur de v rit de Q si l on conna t celle de P quand P est vraie on en d duit que Q est vraie et quand P est fausse on en d duit que Q est fausse Nous n avons pas d fini ce connecteur car il s exprime en fonction de ceux que nous connaissons d j Vous savez peut tre que P amp Q est une double implication comme le sugg re la double fl che En effet P amp Q signifie que P implique Q la proposition directe et que de plus Q implique P la proposition r ciproque En fait on d finit l quivalence par cette propri t la proposition P amp Q vaut par d finition ce que vaut la proposition P Q et Q P Comme ci dessus nous tablissons la table de v rit de l quivalence en proc dant par tapes au calcul de la table de v rit de la proposition complexe P Q et Q P Nous obtenons PIQIP gt QIQ gt PI P gt Q et Q P v v v v v v f f v f f v f f Ji f v v v 212 D monstration de propositions Cette table de v rit correspond l intuition l quivalence de deux propositions n est vraie que dans le cas o les deux propositions ont la m me valeur de v rit D un point de vue logique des propositions quivalentes so
467. r le r soudre il effectue simultan ment l introduction des quations et leur r solution Polymorphisme et sch mas de types Comme en math matiques il arrivera que l ensemble des quations n ait pas une so lution unique mais qu il y ait au contraire une infinit de solutions C est g n ralement le cas en math matiques lorsqu il y a plus d inconnues que d quations Consid rez par exemple le syst me d une quation deux inconnues x et y z y l Il poss de un degr de libert si l on fixe l une des inconnues l autre est calculable instantan ment Ce m me ph nom ne se rencontre dans les syst mes d quations entre types Soit par exemple le syst me t int b tt qui serait engendr par la phrase let f x 1 o tz est le type de f t celui de 1 et t3 celui de x Par remplacement de t nous en d duisons imm diatement ti int to t3 int Il est impossible d aller plus loin dans les remplacements et pourtant le syst me poss de toujours un degr de libert le type t3 peut tre fix arbitrairement Dans le monde des types on fera alors intervenir le polymorphisme en disant que la solution pour t2 au syst me d quations est un sch ma de type avec pour param tre t3 Ce sch ma de type n est autre qu un type de la forme t3 int valable pour tout les types t3 C est ce que l imprimeur des types de Caml crirait a gt int et qui signifie pour tout type a a
468. r c dents imprime_polyn me_ plein ajoute_polyn mes_pleins 1 2 31 l4 5 61 5 7x 9x 2 unit et m me qui l e t cru calculer x x et trouver 0 imprime_polyn me_ plein ajoute_polyn mes_pleins IO 11 CIO 111 0 unit Impression des polyn mes 45 Multiplication des polyn mes On d finit le produit des polyn mes en utilisant les r gles classiques de d veloppement des expressions alg briques En termes savants on dit que l on utilise la distributivit de la multiplication par rapport l addition Par exemple pour tout polyn me Q on a 1 2x 3x2 x Q 1 x Q 2x x Q 3x x Q et donc 1 2x 3 x 4 5x 6x 1 x 4 5x 6x7 2x x 4 5x 6 3x x 4 5x 6x 4 5x 6x 8x 10x 12x 12x 15x 1874 4 13x 28r 277 187 La remarque fondamentale est que le produit des coefficients des mon mes de degr i du premier polyn me et de degr j du second forme une partie du coefficient du mon me de degr i j du produit Par exemple pour les mon mes 2x et 6x le produit 2 x 6 entrera dans la composition du coefficient du mon me de degr trois du r sultat ce qui signifie simplement que 2x x 6x 12x Pour prendre en compte le produit des mon mes 2x et 6x dans le r sultat final il suffit donc d ajouter le produit 2 x 6 dans la case correspondant au coefficient de z du r sultat final Ainsi notre proc dure
469. r courante d une variable C est ce qu on nomme un environnement L environnement sert enregistrer les liaisons des variables leur valeur calcul e lors de leur d finition Les liaisons sont mod lis es par des paires nom de variable valeur associ e tandis que l environnement se repr sente comme une liste de telles liaisons L environnement a donc la structure d une liste d association structure de donn es que nous avons d j utilis e pour mod liser la base de donn es de Cam lia au chapitre 7 On ajoute donc une liaison l environnement en ajoutant une paire nom valeur en t te de la liste qui repr sente l environnement et l on trouve la valeur associ e un nom de variable par une simple recherche l aide de la fonction assoc La fonction assoc est une fonction pr d finie de recherche dans les listes d associations analogue la fonction associ _de de la section 7 3 let rec valeur_expr env function Constante n gt n Somme e1 e2 gt ajoute_nombres valeur_expr env e1 valeur_expr env e2 Produit e1 e2 gt multiplie_nombres valeur_expr env e1 valeur_expr env e2 Diff rence e1 e2 gt soustrais_nombres valeur_expr env e1 valeur_expr env e2 Quotient e1 e2 gt divise_nombres valeur_expr env e1 valeur_expr env e2 Variable s gt assoc s envV valeur_expr string nombre list gt expression gt nombre lt fun gt Les ordres du langage Le
470. r rapport au ou c est dire qu on d veloppe P et Q ou R comme si c tait P x Q R gt gt gt P et Q ou R lt gt P et Q ou P et R Th or me pour toutes propositions R Q P P et Q ou R lt gt P et Q ou P et R Exemples de th or mes 227 Il d montre tout aussi facilement que le ou est distributif par rapport au et ce r sultat n a pas d analogue en arithm tique gt gt gt P ou Q et R lt gt P ou Q et P ou R Th or me pour toutes propositions R Q P P ou Q et R lt gt P ou Q et P ou R Imaginez ce que serait une d monstration la main de cette propri t avec des tables de v rit on aurait huit lignes et huit colonnes Finalement l quivalence est une relation d quivalence ce qui signifie simple ment qu elle introduit une certaine notion d galit Il est videmment heureux qu il en soit ainsi il serait vraiment dommage que l quivalence ne soit pas une relation d quivalence De plus nous avons vu que l quivalence d finissait la no tion de propositions logiquement identiques c est dire gales au point de vue de la logique l quivalence d finit donc bien une notion d galit Formellement une relation d quivalence est une relation r flexive sym trique et transitive L galit en math matiques le symbole a ces propri t s et ce sont les propri t s minimales qu on doit exiger d une relati
471. r types ml type type_simple Variable of variable de_ type Terme of string type_simple vect and variable _de_type mutable niveau int mutable valeur valeur_d une_variable and valeur _d une_variable Inconnue Connue of type_simple type sch ma_de_types param tres variable de_ type list corps type_simple let type_int Terme int II and type_bool Terme bool and type_fl che t1 t2 Terme gt lt1 t211 and type_produit t1 t2 Terme x t1 t21 and type_liste t Terme list lt1l Les types simples sont soit des variables de type soit des types construits Une variable de type poss de un niveau de liaison qui identifie la d finition o la variable a t cr e et une valeur Cette valeur est soit inconnue la variable de type est toujours une inconnue soit connue en ce cas c est un type simple Un type construit se compose d un constructeur de type comme int ou gt et le cas ch ant des arguments du Repr sentation des types 349 constructeur sous forme d un tableau de types simples Les types de base comme int et bool ont z ro argument les types listes ont un argument et les types fl ches et produits en ont deux Pour fournir l intuition de la m thode de r solution nous donnons une in terpr tation graphique de cette m thode Nous expliquons donc graphiquement comment les quations de typage sont prises en compte gr c
472. rancs suisses 4 116 Lires 0 00338617 Livres 9 552 Marks 3 354 Pesetas 0 0394061 Yens 0 05011 l do_list function nom taux gt menu__add_command source Label nom Command function gt label__configure tiqi Text nom tauxi taux synchronise_ zones entr el entr e2 tauxi taux2 liste_de_devises do_list function nom taux gt menu__add_command cible Label nom Command function gt label__configure tiq2 Text nom taux2 taux synchronise_ zones entr e2 entr ei taux2 tauxi liste_de_devises Pour chaque devise nous ajoutons une entr e dans le menu ggurce Cible Source et une entr e dans le menu Cible Les actions as Frans 7 N z Dollars US soci es ces entr es de menus changent le nom de la devise Euros bjiars canadiens dans l tiquette correspondante puis ajustent le taux de con Euros F F version taux1 ou taux2 respectivement et enfin appellent DART Francs belges synchronize_zones pour mettre jour les montants affich s Francs suisses dans les zones d entr e Les taux de conversion utilisent le franc SE comme devise de r f rence ARRS Pesetas pack barre_de_menus Side Side_Top Fill Fill_X Yens pack ligne1 ligne2 Side Side_Top Fill Fill_X mainLoop Le jeu du taquin 199 11 4 Le jeu du taquin Pour conclure ce chapitre nous crivons en CamlTk un jeu de taquin Le taqu
473. rbre seek_in entr e 0 encode entr e sortie codage La fonction pr d finie seek_in positionne le pointeur de lecture d un canal d entr e Le pointeur de lecture du canal entr e qui est la fin du fichier au retour de la fonction Annexes 247 fr quences est donc remis au d but du fichier par l appel seek_in entr e 0 Cela permet encode de relire les octets du fichier compresser Fichier huffman ml let d compresse entr e sortie let arbre input_value entr e in d code entr e sortie arbre 13 4 Annexes Pour finir le programme de compression il reste impl menter les files d attente avec priorit module fileprio et les entr es sorties bit bit module esbit Files d attente avec priorit On rappelle l interface du module fileprio Fichier fileprio mli type at value vide a t and ajoute a t gt int gt a gt at and extraire a t gt int a a t exception File_vide Une premi re repr sentation des files d attente consiste en des listes de paires pri orit l ment tri es par ordre de priorit croissante De la sorte l l ment de priorit minimale est toujours en t te de la liste et la fonction extraire est tr s simple Fichier fileprio ml type a t int a list let vide l let extraire function gt raise File_vide prio elt reste gt prio elt reste
474. re de vous ou Etes vous mari e r ponses_types ce que le programme r pond quand il d tecte un caract re et rien de plus int ressant dans la phrase Typiquement C est moi qui pose les questions e r ponses_aux_phrases_simples pour r pondre aux phrases l emporte pi ce comme Et alors ou Oui R ponse typique Alors expliquez moi ou Donnez moi plus de d tails e r ponses_aux_petits_mots quand le programme n a rien de mieux faire il cherche un mot tr s souvent employ en fran ais qui lui permette de faire une r ponse sens e sans rien comprendre Exemple typique si la phrase contient le mot jamais le programme peut r pondre Jamais me semble un peu fort non e r ponses_aux_mots_int ressants le programme surveille si le patient em ploie des mots psychanalytiques comme p re ou famille et r agit alors en cons quence R ponses typiques Racontez moi vos probl mes quand le mot malheureux est d tect let salutations Faites vous des r ves tranges l Ce sera long et difficile revenez me voir Faites vous souvent des cauchemars souvent Que pensez vous de l amour Votre cas n est pas simple et m me assez Que pensez vous de la sexualit inqui tant A bient t Quels sont vos violons d Ingres Diagnostic simple sans conteste vous tes Qu est ce qui vous int resse dans la vie
475. re du code pour v rifier les types l ex cution ce qui complique la compilation et ralentit l ex cution 284 Compilation de mini Pascal Voici l interface du module typage fournissant la fonction de v rification des types Fichier typage mli open syntaxe type erreur_de_type Ind fini of string variable utilis e mais non d finie Conflit of string expr_type expr_type conflit de types Arit of string int int mauvais nombre d arguments Tableau_attendu x appliqu un non tableau Tableau_interdit of string tableau renvoy en r sultat exception Erreur_typage of erreur_de_type value type_programme programme gt unit and affiche _erreur erreur_de_type gt unit and type_op_unaire string gt expr_type expr_type and type_op_binaire string gt expr_type expr_type expr_type La fonction type_programme signale les erreurs de typage en d clenchant alors l exception Erreur_typage avec pour argument une description de l erreur L erreur peut ensuite tre imprim e par la fonction affiche _erreur Environnements de typage Pour typer une expression ou une instruction il est n cessaire de conna tre les types des variables des fonctions et des proc dures mentionn es dans cette expression ou cette instruction L environnement de typage est une structure de donn es qui associe aux noms de variables leur type courant c est dire le type
476. re elem reste membre a gt a list gt bool lt fun gt Listes d association Les listes d association sont simplement des listes de paires o le premier l ment de la paire est une cl et le second la valeur associ e la cl Pour les tenants de Bourbaki c est le graphe d une fonction donn e en extension Par exemple consid rez une liste d adresses On associe au nom d une personne son adresse let adresses Pierre Caml Domaine de Voluceau 78153 Le Chesnay Cedex Xavier Light 45 rue d Ulm 75005 Paris l adresses string string list Pierre Caml Domaine de Voluceau 78153 Le Chesnay Cedex Xavier Light 45 rue d Ulm 75005 Paris Dans notre programme une liste d association donnera les r ponses possibles associ es aux phrases tr s simples Voici un extrait de la liste d association des phrases simples let r ponses_aux_phrases_simples KC Voulez vous changer de sujet Continuez et alors I Alors expliquez moi Ne soyez pas si agressif non C est vite dit Pourriez vous pr ciser oui I C est un peu rapide Donnez moi plus de d tails Cette liste associe la liste vide correspondant une r ponse vide le tableau de r ponses possibles Voulez vous changer de sujet Continuez Elle as socie la phrase r duite et alors les r ponses Alors expliquez moi Ne soyez pa
477. re information d termine la taille des l ments lors d un acc s au tableau Fichier compil ml let rec type_de_tableau env function Variable nom gt begin match cherche_variable nom env with typ Array inf sup ty gt inf sup ty end Acc s_tableau argi arg2 gt match type_de_tableau env argi with _ _ Array inf sup ty gt inf sup ty Comme les tableaux ne peuvent tre renvoy s comme r sultat d un appel de fonction une expression bien typ e de type Array ne peut tre qu une variable ou un acc s dans un tableau multidimensionnel ces deux cas sont donc les seuls consid rer dans type_de_tableau La deuxi me fonction auxiliaire d termine si l valuation d une expression peut interf rer avec l valuation d une autre Deux expressions n interf rent pas si leurs 294 Compilation de mini Pascal r sultats et les effets qu elles effectuent ne d pendent pas de l ordre dans lequel on les value Une expression qui contient un appel de fonction est susceptible d interf rer avec une autre expression la fonction peut crire quelque chose l cran ou modifier une variable globale De m me une expression qui fait intervenir la valeur d une variable globale peut interf rer avec une autre expression qui va modifier cette variable globale l occasion d un appel de fonction On se convainc facilement qu une expression ne contenant ni variables globale
478. re ne contenant pas d j un r sultat interm diaire si oui on lib re certains des registres utilis s en stockant leur valeur dans la pile avant l valuation de l expression puis en les rechargeant depuis la pile une fois l expression valu e Fichier compil ml let dernier_registre 24 let rec besoins env function Constante c gt 0 Variable nom gt 0 Application fonc args gt dernier_registre Op_unaire op arg gt besoins env arg Op_binaire op arg1 arg2 gt besoins_op_binaire env arg1 arg2 Acc s_tableau argi arg2 gt besoins_op_binaire env argi arg2 and besoins_op_binaire env arg1 arg2 Compilation 295 let b1 besoins env argi and b2 besoins env arg2 in if b1 lt b2 amp amp sans_interf rences env argi sans_interf rences env arg2 then max b2 b1 1 else max bi b2 1 L valuation des expressions peut utiliser tous les registres dont les num ros sont compris entre 1 et dernier_registre pour stocker des r sultats interm diaires Les registres au dessus de dernier_registre sont r serv s pour d autres usages tempo raires pointeur de pile La constante dernier_registre est le nombre de registres du processeur que nous pouvons utiliser pour l valuation des expressions On suppose que l application d une fonction ne pr serve aucun de ces registres la fonction appel e peut les utiliser li brement pour valuer des expressions arbitrairement compl
479. re_registre reg 0 then pico pc lt adresse Branz reg adresse gt if lire_registre reg lt gt 0 then pico pc lt adresse Scall appel_syst me gt crire_registre 1 ex cute_appel_syst me appel_syst me lire_registre 1 Stop gt raise Arr t reg2 argi arg2 argi land arg2 argi lor arg2 argi lxor arg2 argi 1sl arg2 argi asr arg2 if arg1 lt arg2 then 1 else 0 if arg1 lt arg2 then 1 else 0 if arg1 arg2 then 1 else 0 Ex cution d un programme complet L ex cution d un programme complet fonction ex cute consiste charger la m moire avec le programme allouer la m moire des donn es initialiser le pointeur de pile et le compteur ordinal puis lancer une boucle sans fin de cycles d horloge qui ne s arr te qu la rencontre de l exception Arr t Enfin puisque nous avons choisi par convention que le pointeur de pile serait le registre 30 et que la pile cro trait vers le bas de la m moire le registre sp est initialis la plus grande adresse m moire possible plus un au d marrage de la machine Le simulateur 265 Fichier simul ml let ex cute programme taille _m moire_en_octets let taille _m moire_en_mots taille_m moire_en_octets 3 4 in pico code lt programme pico m moire lt make_vect taille _m moire_en_mots 0 pico registres 0 lt 0 pico registres sp lt taille_m moire_en_mots taille_du_mot pico pc
480. remarque alors que la cha ne s ne varie jamais pendant les appels la fonction pelle_aux on la supprime purement et simplement des arguments de pelle_aux car s est li e l ext rieur de pelle_aux par la fonction pelle On obtient maintenant let pelle s let rec pelle_aux i if i lt string_length s then begin print_char s i l print _ char pelle_aux i 1 end in pelle_aux 0 pelle string gt unit lt fun gt On constate alors que la fonction pelle_aux n est autre qu une boucle for d guis e son premier argument est 0 son dernier argument string_length s 1 et pelle_aux augmente l indice de 1 chaque appel r cursif On r crit donc facilement pelle avec une boucle for let pelle s for i 0 to string_length s 1 do print_char s i l print _ char done pelle string gt unit lt fun gt pelle Caml Caml unit C est videmment le cas aussi pour compte et compte_ _rebours let compte n for i 1 to n do print_int i print _string compte int gt unit lt fun gt w done let compte_ _rebours n for i n downto 1 do print_int i print_string done compte_ _rebours int gt unit lt fun gt compte 10 compte_ _rebours 10 123456789101098765432 1 unit On peut donc h siter entre les deux styles de programmation Chaque fois qu une d finition r cursive code une boucle f
481. remplace par sa valeur Malheureusement cette phase ne suffit pas car le programmeur peut faire r f rence des tiquettes en avant c est dire encore inconnues car pas encore rencontr es C est le cas de l instruction jmp fact r 31 qui est assembl e alors que l tiquette fact sera lue trois instructions plus loin Dans ce cas l assembleur laisse l adresse de l tiquette z ro et note que l instruction assembl e est compl ter lorsque l tiquette sera connue C est le r le de la seconde phase d assemblage que de repasser sur ces instructions incompl tes et de les modifier avec les adresses d sormais d termin es La fonction r soudre_ tiquette se charge de ce travail appel backpatching en anglais Pour obtenir l adresse absolue des tiquettes l assembleur g re un compteur ordi nal virtuel qu il incr mente chaque nouvelle instruction assembl e Il engrange ses r sultats dans un tableau d instructions assembl es Ces quantit s font partie de l tat de l assembleur avec la table des tiquettes et la liste des tiquettes r soudre La table des tiquettes est une table de hachage comme celles d crite la section 12 8 Fichier stockage ml open code type tat_de_l assembleur mutable pc int mutable code instruction vect table_ tiq string int hashtbl__t mutable _r soudre int string list let asm pc 0 code table_ ti
482. res du langage graphique Syntaxe et s mantique Notions d analyses syntaxique et lexicale Analyse lexicale et syntaxique Ajout des proc dures 10 Programmes ind pendants et modules 10 1 10 2 10 3 10 4 10 5 10 6 Chargement de fichiers Programmes ind pendants Entr es sorties de base Programmes en plusieurs modules Interfaces de modules Compilations interactives 11 Interfaces graphiques 11 1 11 2 11 3 11 4 11 5 Structure d une interface graphique Relier des composants entre eux Un convertisseur de devises Le jeu du taquin Pour aller plus loin IT Exemples complets Avertissement 12 D monstration de propositions 12 1 12 2 12 3 12 4 12 5 12 6 12 7 12 8 12 9 La logique math matique Calculs de tables de v rit Le principe des d monstrations Repr sentation et v rification des propositions Syntaxe concr te des propositions Le v rificateur de tautologies Exemples de th or mes Pour aller plus loin l analyseur lexical universel Pour aller encore plus loin le hachage 13 Compression de fichiers 13 1 13 2 13 3 13 4 13 5 13 6 La compression de donn es Plan du programme L algorithme de Huffman Annexes Mise en pratique Pour aller plus loin 14 Simulation d un processeur 14 1 14 2 14 3 14 4 Le pico processeur Le simulateur L assembleur Pour aller plus loin ix 158 159 160 161 168 179 179 180 181 183 187 190 193 193 194 196 199 20
483. ression Bool en of bool Nombre of int Paire of expression expression Nil Cons of expression expression and motif Motif_variable of string Motif_bool en of bool Motif_nombre of int Motif_paire of motif motif Motif _nil Motif_cons of motif motif and d finition r cursive bool nom string expr expression La pauvret apparente de ce langage est compens e par le fait que de nombreuses constructions de Caml sont d riv es des constructions de mini Caml Par exem ple la construction match e with p e n est autre qu une application de fonction function p e1 e De m me la construction conditionnelle if cond then e1 else ez se ram ne match cond with true gt e1 false e2 D autre part toutes les op rations primitives op rations arithm tiques par exemple se pr sentent sous la forme d identificateurs pr d finis Une phrase mini Caml est soit une expression soit une d finition Contrairement Caml nous n avons pas de d clarations de types Fichier syntaxe mli type phrase Expression of expression D finition of d finition value lire_phrase char stream gt phrase L impl mentation du module syntaxe est tout enti re consacr e la fonction d analyse syntaxique lire_phrase L analyseur syntaxique de mini Caml utilise exactement les m mes techniques que celui pour mini Pascal Nous ne d taillerons donc pas la fon
484. ression dans le langage En effet argument d un ordre avance par exemple ne se r duit plus une constante ce peut tre maintenant l argument d une proc dure Par exemple pour d finir la proc dure qui dessine un Ajout des proc dures 169 carr de c t c nous crirons une r p tition o l ordre avance a pour argument la variable c pour carr c r p te 4 avance c td 90 La syntaxe concr te que nous employons s inspire de celle du langage Logo les noms de variables sont pr c d s d un signe deux points comme dans x et les d finitions de proc dures sont introduites par le mot pour Tous les ordres qui avaient pr c demment un argument num rique auront main tenant une expression en argument Nous tendons un peu ce langage des expressions pour autoriser les quatre op rations l mentaires On trouvera donc dans le type des ex pressions outre les nombres et les variables repr sent s par les constructeurs Constante et Variable les quatre constructeurs Somme Produit Diff rence et Quotient Ces constructeurs prennent en argument une paire d expressions qui repr sente les deux op randes type expression Constante of nombre Somme of expression expression Produit of expression expression Diff rence of expression expression Quotient of expression expression Variable of string Le type expression est d fini L valuateur des expressions Nous dev
485. rge pour la projection de s lectionner la composante qui l int resse let paire x y function projection gt projection x y paire a gt b gt a gt b gt c gt c lt fun gt let fst paire paire function x gt function y gt x and snd paire paire function x gt function y gt y fst Ca gt b gt a gt c gt c lt fun gt snd Ca gt b gt b gt c gt c lt fun gt let paire_un_true proj paire 1 true proj paire_un_true int gt bool gt a gt a lt fun gt fst paire_un_true Ant 1 snd paire_un_true bool true On reproduit alors exactement les m mes exemples que ci dessus sans utiliser de struc tures de donn es Assez curieusement la complexit de l algorithme de typage a deux sources la recherche du type de la phrase videmment mais aussi la simple impression du type r sultat On montre en effet que la repr sentation interne du type des phrases sans let est toujours fortement partag e la taille du type est au plus lin aire par rapport la taille du programme Si donc on prend soin de ne pas d partager les types pendant 362 Un synth tiseur de types le typage et qu on crit les types en exhibant leur partage l algorithme de synth se de type devient lin aire pour les expressions qui ne comportent pas de let Lorsqu on utilise la construction let il n exist
486. rs lancer Caml Light puis entrer include logo logo une phrase Logo logo une autre phrase Logo quit Cela vaut mieux certes que de r crire tout le code du syst me Logo mais ce n est pas encore id al il faut expliquer aux utilisateurs que chaque phrase Logo doit tre pr c d e de logo et suivie de ce qui n a rien de naturel s ils ne connaissent pas Caml Il serait bien meilleur d avoir un programme logo qu on puisse lancer comme n importe quel autre programme de la machine et sous lequel on puisse entrer directement les phrases Logo ex cuter Pour ce faire il faut abandonner le syst me Caml Light interactif et utiliser le compilateur ind pendant Ce dernier transforme un fichier contenant des phrases Caml Light en un programme directement ex cutable Supposons que le fichier hello ml contienne les trois phrases let message Bonjour tout le monde print_string message print_newline Pour compiler ce fichier il faut lancer le compilateur Caml Light partir de l interpr te de commandes de votre machine Rappelons que l interpr te de commandes est le pro gramme syst me qui permet de lancer d autres programmes en tapant des lignes de commandes C est par exemple le programme Invite de commande de MS Windows ou l un des nombreux shells du syst me Unix Sur le Macintosh le syst me standard ne fournit pas d interpr te de commandes Le compilateur ind pend
487. rs lisez ce chapitre il est fait pour vous Nous y apprendrons une nouvelle mani re d utiliser l ordinateur Jusqu pr sent nous nous en servions pour obtenir les solutions des probl mes que nous savions r soudre mais qui demandaient trop de calculs math matiques pour que nous les traitions la main C est l emploi de l ordinateur le plus r pandu actuellement la machine sert effectuer un tr s grand nombre de fois des op rations simples pensez des logiciels de gestion paye ou comptes en banque Avec la r cursivit on l ve la programmation un rang autrement plus noble on crit des programmes qui r solvent des probl mes que l on ne sait pas forc ment r soudre soi m me Parvenir diriger une machine pour qu elle trouve pour nous la solution d un probl me est r ellement fascinant il est m me grisant de voir appara tre cette solution au terminal quand elle est le r sultat de l ex cution d un programme qu on a soi m me crit sans avoir conscience de savoir r soudre le probl me 2 1 Fonctions r cursives simples Notion de r cursivit Une d finition r cursive est une d finition dans laquelle intervient le nom qu on est en train de d finir Cela correspond dans le langage courant une phrase qui se mord la queue L exemple typique est la r ponse la question Qu est ce qu un go ste Quelqu un qui ne pense pas moi Il est clair qu on soup onne l
488. rs true Cela explique le r sultat de est_un 2 Cela explique aussi le message du compilateur ce cas de filtrage est inutile Le compilateur s est rendu compte que le cas _ gt ne servira jamais C est Structures de donn es et filtrage 121 pour viter ce genre de confusions qu on utilise la convention de faire commencer les noms de constructeurs par une majuscule et d crire les variables dans les filtres en minuscules Retenons que Toute variable dans un filtre est une nouvelle variable Lin arit du filtrage Il faut galement savoir que le filtrage en Caml est lin aire ce qui signifie qu un nom de variable ne peut appara tre qu une seule fois dans un filtre Cette contrainte est viol e le plus souvent lorsqu on veut tester l galit de deux morceaux d une valeur Voici une tentative erron e de d finir la fonction d galit si le couple argument comporte deux composantes identiques on renvoie vrai et sinon on renvoie faux let gal function x x gt true _ gt false Entr e interactive gt x x gt true 2 L identificateur x est d fini plusieurs fois dans ce motif Les tests d galit op r s par le filtrage ne concernent que les constantes les construc teurs Les tests d galit plus g n raux ne s expriment pas par filtrage ils doivent faire l objet d une alternative explicite un if then else dans l expression d une clause de filtrage ou b
489. rtaine inefficacit dans les ma nipulations d objets allou s Pour essayer de r duire cette inefficacit une autre voie prometteuse a t propos e r cemment pour admettre des donn es de taille h t rog ne comme les tableaux allou s plat de mini Pascal tout en conservant le polymorphisme param trique de Caml il s agit de modifier la repr sentation des donn es au cours de l ex cution des programmes Ainsi certaines fonctions non polymorphes travaillent avec des donn es occupant plus d un mot par exemple des flottants sur deux mots tandis que les fonctions polymor phes travaillent syst matiquement avec des donn es d un mot Lorsque des fonctions polymorphes et des fonctions normales changent des donn es celles ci sont allou es dans un objet structur l entr e des fonctions polymorphes qui ne connaissent pas la repr sentation sp cifique des donn es ainsi les fonctions polymorphes re oivent tou jours un objet de taille fixe entier ou pointeur sur leur argument Sym triquement la sortie des fonctions polymorphes les donn es sont extraites de l objet structur qui les contient et remises plat pour tre pass es aux fonctions monomorphes qui con naissent leur repr sentation Il va sans dire que cette m thode est bien plus complexe que la pr c dente mais donne g n ralement de meilleurs r sultats Actuellement tous les syst mes Caml fonctionnent avec des donn es de taille uniforme
490. ry uncurry f id_curry a gt b gt c gt a gt b gt c lt fun gt let id_uncurry f compose uncurry curry f id_uncurry a b gt c gt a b gt c lt fun gt Une fonctionnelle inutile Consid rez la fonctionnelle suivante qui applique une fonction f donn e un argu ment x donn let applique f x f x applique a gt b gt a gt b lt fun gt Cette fonctionnelle ne sert rien D abord si vous examinez soigneusement son type vous vous rendrez compte que c est une sp cialisation du type de l identit a gt b gt a gt best une abr viation pour a gt b gt a gt b c est dire a gt a avec a sp cialis en a gt b Donc applique pourrait bien ne rien faire comme la fonction identit On le d montre facilement en utilisant toujours la r gle n avec l argument x cette fois let applique f x f x quivaut let applique f f ce qui d montre que applique est s mantiquement quivalente l identit sp cialis e aux fonctions En effet applique impose son argument f d tre fonctionnel puisqu elle l applique l argument x Cela nous fournit un exemple o l application de la r gle 7 change le type de la fonction qu on d finit le rendant plus g n ral let applique f f applique a gt a lt fun gt PI pr DY P y PA
491. s string list les copains Salut J tri_par_insertion function x gt function y gt le_string x y Salut les copains string list Salut copains les Remarque de complexit on d montre que ce tri est quadratique O n en moyenne sur un jeu de donn es tir es au hasard Dans le pire des cas c est dire quand le jeu de donn es n cessite le plus d op rations ce qui correspond pour ce tri une liste tri e en ordre inverse le tri par insertion est galement quadratique En revanche il est lin aire pour une liste d j tri e 5 4 Fonctionnelles simples sur les listes Les listes comme toutes les structures de donn es polymorphes se pr tent naturelle ment la d finition de fonctionnelles r utilisables dans de nombreuses situations Nous pr sentons dans cette section quelques unes de ces fonctionnelles parmi les plus sim ples nous en verrons d autres plus complexes la section 5 9 Faire une action sur les l ments d une liste tant donn es une fonction f et une liste l la fonctionnelle do_list applique f tour tour tous les l ments de l Cela correspond donc effectuer des appels f en s quence sur les l ments de l Autrement dit valuer do_list f e1 e2 en signifie ex cuter la s quence begin f e1 f e2 f en O end Par exemple 82 Listes do_list print_int 1 2 3l 123 unit do_list
492. s 18 1 Principes de la synth se de types Les quations entre types La synth se de types est analogue la r solution d quations math matiques On aura donc la notion de variables de constantes transpos e dans le domaine des types variables de type types constants la diff rence des math matiques o le probl me est de r soudre un ensemble d quations donn es l avance le synth tiseur de type doit d couvrir dans le programme qui lui est soumis l ensemble des quations r soudre Ces quations sont cependant tr s naturelles Par exemple si l on doit typer l application f x on produira les quations type de f ti t type de x t type de f x t Ici les inconnues sont des types t et t2 Ces nouvelles variables seront automatique ment introduites par le synth tiseur de type On comprend que si chaque application de fonction introduit deux nouvelles inconnues et trois quations suppl mentaires le probl me m ne vite un tr s grand nombre d inconnues et d quations Cependant l algorithme de synth se de type aura le souci de ne pas introduire de nouvelles in connues inutilement Par exemple si l on sait d j que f a pour type ty ty on 340 Un synth tiseur de types se contentera d utiliser les types ty1 et ty2 qui interviennent d j dans le probl me De plus l algorithme n attend pas d avoir enti rement construit le syst me d quations pour commence
493. s tude de cas 99 interm diaires de la fonction L optimisation ne d pend donc pas obligatoirement du style de programmation utilis puisqu une m me id e sert dans les deux styles et pour des programmes diff rents La fonction implose version fonctionnelle La fonction implose concat ne toutes les cha nes d une liste de cha nes Nous en avons d j crit la version la plus na ve dans la section 5 9 Raisonnons graphiquement pour obtenir la concat nation de toutes les cha nes d une liste il faut r crire la liste en rempla ant les par des et le symbole final par la cha ne vide Alg briquement si l on note lc la liste argument c1 C2 Cn On a implose c1 C2 tale ee og list_it prefix le implose gt list_it prefix le C1 NC C1 De la m me fa on mais en utilisant it_list au lieu de list_it implose do Mere s es it_list prefix lc On obtient donc let implose lc list_it prefix lc implose string list gt string lt fun gt let implose2 lc it_list prefix lc implose2 string list gt string lt fun gt implose2 se simplifie par la r gle 7 pour donner un code extr mement similaire celui de somme op ration binaire prefix au lieu de prefix et l ment neutre au lieu de 0 nn 239 let implose2 it_list prefix implose2 string list gt string lt fun gt
494. s de un coefficient et un degr pour mod liser les mon mes nous d finirons donc un type produit avec deux caract ristiques coefficient et degr toutes deux de type entier type mon me coefficient int degr int Le type mon me est d fini Pour construire une valeur de ce type on se contente d num rer ses caract ristiques particuli res let mi coefficient 1 degr O mi mon me coefficient 1 degr 0 Les types produit 117 Acc s aux composantes des enregistrements Pour acc der l une des caract ristiques d un objet de type produit il suffit de faire suivre l objet d un point et du nom de la caract ristique C est analogue au de l acc s dans les tableaux et les cha nes de caract res mi coefficient int 1 mi degr int 0 Ce que nous avons appel nom de caract ristique porte le nom technique d tiquette Une caract ristique s appelle aussi une rubrique ou encore un champ de l enregistrement Les tiquettes permettent de se lib rer de l ordre dans lequel on nomme les caract ristiques le compilateur se charge de les mettre dans le bon ordre Ainsi si l on intervertit l ordre des tiquettes la valeur produite est la m me let m2 degr 0 coefficient 1 m2 mon me coefficient 1 degr 0 mi m2 bool true Filtrage des types enregistrement Le filtrage s t
495. s ni appels de fonctions n interf re avec aucune autre expression Pour rester simple on suppose ici que tout appel de fonction est susceptible de faire des effets Pour faire les choses plus finement il faudrait analyser aussi le corps de la fonction appel e pour voir s il peut faire des effets en s ex cutant Fichier compil ml let rec sans_interf rences env function Constante c gt true Variable nom gt let var cherche_variable nom env in begin match var emplacement with Global_indirect _ Global_direct _ gt false Local_indirect _ Local_ direct _ gt true end Application fonc args gt false Op_unaire op arg gt sans_interf rences env arg Op_binaire op argi arg2 gt sans_interf rences env argi amp amp sans_interf rences env arg2 Acc s_tableau argi arg2 gt sans_interf rences env argi amp amp sans_interf rences env arg2 La derni re fonction auxiliaire d termine les besoins en registres d une expres sion de combien de registres libres l valuation de l expression a besoin pour stocker ses r sultats interm diaires Cette information est pr cieuse pour d terminer quand il est n cessaire de sauvegarder des r sultats interm diaires sur la pile La strat gie que nous allons employer est la suivante avant d valuer une expres sion on regarde si ses besoins en registres sont sup rieurs au nombre de registres inu tilis s c est di
496. s qui se lit aussi bien l endroit qu l envers Pour d terminer si un mot constitue un palindrome il suffit de v rifier que ses premier et dernier caract res sont identiques puis de v rifier que le mot situ entre ces deux caract res est lui aussi un palindrome m mes caract res cha ne s clolololololololololc palindrome s Il faut aussi remarquer qu un mot r duit un seul caract re est un palindrome et que la cha ne vide est elle aussi un palindrome puisqu elle se lit aussi bien l endroit qu 26 R cursivit l envers Pour obtenir une sous cha ne d une cha ne de caract res on utilise la fonction pr d finie sub_string sous cha ne qui extrait une sous cha ne partant d un indice donn et d une longueur donn e sub_string Le langage Caml 3 7 string langage En particulier sub_string s 1 string_length s 2 retourne la cha ne s priv e de son premier et de son dernier caract re Ceci se traduit par la fonction r cursive suivante let rec palindrome s let longueur string_length s in if longueur lt 1 then true else if s 0 s longueur 1 then palindrome sub_string s 1 longueur 2 else false palindrome string gt bool lt fun gt palindrome serres palindrome toto bool true bool false Op rateurs bool ens Cette fonction s crit plus l gamment
497. s cas de base du type comme par exemple les constructeurs sans arguments correspondent souvent des cas de base des fonctions r cursives sur ce type Les cartes On mod lise tr s ais ment un jeu de cartes en utilisant les types somme Les couleurs forment un type num r type couleur Tr fle Carreau Coeur Pique Le type couleur est d fini et les cartes un type somme plusieurs possibilit s selon les valeurs faciales des cartes type carte As of couleur Roi of couleur Dame of couleur Valet of couleur Petite_carte of int couleur Le type carte est d fini Dans cette d finition nous avons choisi de regrouper toutes les cartes qui ne sont pas des figures sous la m me d nomination Petite_carte On aurait pu aussi continuer l num ration avec des constructeurs Dix Neuf Huit etc Pour illustrer le filtrage sur les types somme nous d finissons la valeur d une carte la belote Cette valeur d pend d une couleur particuli re l atout choisie par les joueurs chaque tour Les cartes dont la valeur change sont le valet et le neuf le neuf compte d ordinaire pour 0 mais vaut 14 quand il est de la couleur de l atout et le valet d atout vaut 20 au lieu de 2 d ordinaire D autre part les dix valent 10 points et les autres petites cartes 0 let valeur_d une_carte couleur_d atout function As _ gt 11 Roi _ gt 4 Dame _ gt 3 Valet c gt i
498. s f en utilisant les l ments de la liste l comme seconds arguments de f La valeur de base b est utilis e pour le premier argument du premier appel f puis le r sultat de chaque appel f est pass en premier argument de l appel suivant it_list est caract ris e par it list f b e1 e2 re fa f f bei e2 n Le code de it_list est let rec it_list f b function D gt b x l gt it_list f f b x 1l it_list a gt b gt a gt a gt b list gt a lt fun gt Intuitivement si l on peut dire it_list fait de la r criture de liste elle remplace tous les de la liste par f consid r e comme un op rateur binaire infixe et ajoute la valeur initiale b au premier appel f Graphiquement l effet calculatoire de it_list se repr sente par la transformation Fonctionnelles complexes sur les listes 95 it_list 7 I Y e jt list f lb ZIN JUN SE f En JON JUN e2 se ce CEn 1 N PR JUN En b 1 Par exemple supposons que f soit l addition Nous obtenons it_list f b e1 e2 en b e1 e2 en Maintenant nous pouvons crire la fonction somme en utilisant it_list let ajoute x y x y ajoute int gt int gt int lt fun gt let somme 1 it_list ajoute O l somme int list gt int lt fun gt somme 1 2 3 l int 6 Allons encore un peu plus loin il est inutile de d finir la fon
499. s false par l entier 0 et true par l entier 1 Un tableau type array est stock dans un certain nombre de mots m moire contigus et repr sent par l adresse m moire du premier l ment Dans le cas d un tableau de tableaux c est dire un tableau multidimensionnel deux approches sont possibles l allocation structur e ou l allocation plat Avec l allocation structur e une valeur de type array 1 21 of array 1 2 of integer est repr sent e par un tableau de deux pointeurs vers deux tableaux de deux entiers Avec l allocation plat une valeur du m me type est un bloc m moire de quatre mots contenant les deux tableaux de deux entiers mis c te c te Allocation structur e Allocation plat t t 1 1 t 1 2 t 2 1 t 2 2 E m FER srl tn gere Nous allons utiliser l allocation plat qui est plus compacte et plus efficace l acc s que l allocation structur e bien qu elle complique l g rement la compilation En particulier pour calculer le d calage entre le d but d un tableau et l l ment auquel on veut acc der il faut conna tre la compilation la taille des l ments du tableau Heureusement cette taille se d duit facilement du type des l ments du tableau qui est une information connue la compilation La fonction taille_du_type ci dessous calcule le nombre d octets occup s par la repr sentation d un objet du type donn Fichi
500. s fonctions sur les listes tude de cas 101 Quand n est grand n x n 1 2 est proche de n 2 Notre fonction a donc une complexit de l ordre de n elle est quadratique Nous avons d j vu que c est une complexit importante Nous allons tenter de l am liorer La fonction implose version imp rative L id e tr s simple est de calculer d abord la longueur de la cha ne n cessaire au r sultat final de l allouer puis d y copier toutes les cha nes de la liste let implose cha nes let longueur ref 0 in do_list function ch gt longueur string_length ch llongueur cha nes let r sultat create_string llongueur and position ref O in do_list function ch gt blit_string ch 0 r sultat lposition string_length ch position lposition string_length ch cha nes r sultat implose string list gt string lt fun gt La complexit de cette version est alors d une seule allocation de cha ne et de n copies de caract res cette version est donc lin aire La diff rence d efficacit est norme pour 104 cha nes de caract res la premi re version n cessite 108 2 copies soit 5000 fois plus que l algorithme lin aire En d autres termes si la version lin aire demande 1 seconde pour r aliser la concat nation des 10 cha nes alors la version quadratique n cessite plus de 1 heure de calcul Nous avons ainsi optimis la fonction implose en passant dans le mond
501. s identificateurs d finis par le module ce qui les rend ainsi inaccessibles depuis l ext rieur du module Pour ce faire il faut crire une interface au module L interface d un module contient des d clarations pour tous les identificateurs du module que l on veut rendre visibles de l ext rieur les identificateurs d finis dans le module mais non d clar s dans l interface seront automatiquement cach s L interface d un module r side dans un fichier ayant le m me nom que le module mais avec l extension mli Par opposition le fichier avec l extension ml qui contient les d finitions du module s appelle l impl mentation du module Par exemple voici le fichier d interface du module crayon value vide_ cran unit gt unit and fixe_crayon bool gt unit and tourne float gt unit and avance float gt unit Comme on le voit les d clarations d identificateurs sont introduites par le mot cl value et consistent en le nom de l identificateur suivi de son type Les interfaces peuvent aussi 188 Programmes ind pendants et modules contenir des d finitions de types et d exceptions Par exemple l interface du module alex rend public le type des lex mes en plus de la fonction d analyse lexicale Fichier alex mli type lex me Mot of string Symbole of char Entier of int Flottant of float value analyseur_lexical char stream gt lex me stream On trouvera en figure 10 2 la
502. s langages fonctionnels comme Haskell fonctionnent selon ce mode de passage des param tres on les appelle les langages paresseux Leur avan tage est videmment qu ils peuvent terminer des calculs quand un langage en appel par valeur bouclerait ou chouerait D autre part ce type de langages permet la ma nipulation ais e de structures de donn es potentiellement infinies on ne calcule de la structure de donn es que la partie strictement n cessaire l obtention du r sultat final Un cueil majeur de ces langages est que les effets y sont prohib s il est en effet tr s difficile de pr dire quand le calcul d un argument va se d clencher donc impos sible de savoir quand vont avoir lieu les effets de bord qu il comporte ventuellement Des m canismes sp ciaux comme par exemple les monades sont donc n cessaires pour traiter les entr es sorties et les exceptions L impl mentation d un valuateur pour ce type de langage repose sur la cr ation de fermetures plus techniquement appel es suspensions ou gla ons pour les arguments des fonctions on enferme ainsi le code qui permet de calculer la valeur avec son environnement de d finition quand on doit valuer une variable on lance alors l ex cution du code de sa fermeture dans l environnement qui l accompagne d gel du gla on Dans le cas de l appel par n cessit il faut en fait cr er une r f rence qui est mise jour en fin de d gel Les op
503. s les fonctions les proc dures et le corps du programme Fichier typage ml let type_programme prog let env_global list_it ajoute_var prog prog_variables environnement _initial prog prog_proc dures prog prog_fonctions in try do_list type_proc dure env_global prog prog_proc dures do_list type_fonction env_global prog prog_fonctions type_instr env_global prog prog_corps with Pas_trouv nom gt raise Erreur_typage Ind fini nom Traitement des erreurs de typage Il reste afficher les messages d erreur On utilise pour cela les fonctions de bib lioth que prerr_int et prerr_string de pr f rence print_string et print_int car les premi res affichent sur la sortie d erreur standard et non sur la sortie standard comme les secondes Fichier typage ml let rec affiche_type function Integer gt prerr_string integer Boolean gt prerr_string boolean Array inf sup ty gt prerr_string array prerr_int inf prerr_string prerr_int sup prerr_string of affiche_type ty let affiche_erreur function Ind fini nom gt prerr_string Nom inconnu prerr_string nom prerr_endline Conflit message type_attendu type_r el gt prerr_string Conflit de types prerr_string message prerr_string devrait avoir le type Compilation 289 affiche_type type_attendu prerr_string mais a le type prerr_endline Arit nom nbr_param tres
504. s o l on range indiff remment des donn es ou des instructions C est encore une fois pour simplifier la simulation que nous avons divis la m moire en deux zones pour faciliter le d codage des instructions que nous gardons sous forme symbolique L alternative aurait t de coder effectivement les instructions sous la forme de nombres entiers et de les d coder au moment de leur ex cution La proc dure de codage et de d codage n est pas tr s int ressante et alourdirait inutilement notre pr sentation Jeu d instructions Le jeu d instructions de la pico machine est r sum dans la figure 14 2 Comme sur la plupart des processeurs RISC les op rations arithm tiques et logiques ont un format Le pico processeur Notations r nom de registre r 0 r 1 r 31 o nom de registre ou constante enti re 12 34 a constante enti re Syntaxe Instruction Effet add r1 0 72 sub r1 0 72 mult r1 0 r2 div r1 0 r2 and r1 0 72 or r1 0 72 xor r1 0 72 shl r1 0 72 shr r 0 r2 slt r1 0 r2 sle r1 0 72 seq r1 0 72 load r1 0 72 store r1 0 72 jmp o r braz r a branz r a scall n stop Addition enti re Soustraction enti re Multiplication enti re Quotient entier Et bit bit Ou bit bit Ou exclusif bit bit D calage arithm tique logique gauche D calage arithm tique logique droite Test inf rieur Test inf rieur ou gal Test ga
505. s ordres s enrichissent de trois nouvelles constructions l ordre Stop qui arr te une proc dure l ordre Ex cute qui ex cute une proc dure en l appliquant la liste de ses arguments et enfin une construction conditionnelle Si L ordre Si ex cute une liste d ordres ou une autre selon qu une condition est remplie Pour simplifier la condition est r duite la comparaison gt sur les nombres Le nouveau type ordre comprend donc les m me constructeurs de base que l ancien Av Re Rep et les trois nouveaux constructeurs Stop Si et Ex cute type ordre Av of expression Re of expression Td of expression Tg of expression Lc Bc Ve Rep of expression ordre list Stop Si of expression expression ordre list ordre list Ex cute of string expression list Le type ordre est d fini Ajout des proc dures 171 La d finition des proc dures et l ex cution des ordres La construction pour permet de d finir de nouvelles proc dures Lorsqu une proc dure est d finie son nom est enregistr avec son corps et la liste de ses arguments dans la liste d association globale proc dures_d finies De m me que pour les vari ables on recherche donc le corps et la liste d arguments d une proc dure en cherchant sa valeur associ e dans la liste des proc dures d j d finies type proc dure param tres string list corps ordre list Le type proc dure est d fini let proc dures_
506. s pas Avez vous de graves probl mes Cherchez un peu Parlez moi de vos probl mes C est vident pour tout le monde sauf pour Cam lia 137 vous r fl chissez Si vous ne m expliquez pas mieux comment C est vous de trouver la r ponse vous comprendre Cherchez bien au fond de vous m me vous le Ne r pondez pas toujours oui ou non savez en fait l Dont acte let r ponses_aux_phrases_simples Et pour quelles raisons CCE et alors l Voulez vous changer de sujet l Alors expliquez moi Continuez Ne soyez pas si agressif Continuez vous m int ressez Alors j aimerais avoir plus d informations Je vous coute l dessus Vous n avez rien d autre dire Zorro est arriv Continuez je vous prie Et alors et alors expliquez vous C est tout ce que vous avez dire C tait un test pour savoir si vous M avez vous tout dit l dessus suiviez Je n en sais pas encore assez sur vous encore continuez l On peut changer de sujet si vous voulez quoi Il faut bien crever l abc s Excusez moi je pensais autre chose Les choses importantes doivent tre continuons dites R fl chissez Il faut savoir affronter les probl mes Changeons de sujet s il vous pla t Je suis plus t tue que vous Je me comprends Pensez vous que je radote Il me semblait pourtant a
507. s pour 1 franc and taux2 ref 6 55957 francs pour 1 euro bind entr ei KeyRelease BindSet l synchronise zones entr ei entr e2 tauxi taux2 bind entr e2 KeyRelease BindSet l synchronise zones entr e2 entr el taux2 tauxi Ci dessus nous associons la fonction synchronise_zones l v nement rel cher une touche enfonc e KeyRelease dans les deux zones d entr e La fonction bind g re les associations de fonctions Caml des v nements elle prend en arguments le composant concern une liste d v nements et de modificateurs ici KeyRelease signifiant la rel che d une touche sans modificateurs particuliers et une action effectuer ici BindSet signifiant la d finition d une nouvelle liaison on dispose aussi de BindRemove pour enlever toutes les liaisons et de BindExtend pour rajouter une liaison Nous avons choisi de li l v nement KeyRelease plut t que KeyPressed appui d une touche afin que la fonction Caml soit appel e apr s l insertion du caract re frapp dans la zone d entr e et non pas avant ce qui produirait des r sultats visuellement faux pack tiqi Side Side_Left lignet pack entr e1 Side Side_Right tiq1 entr e1 pack tiq2 Side Side_Left pack entr e2 Side Side_Right pack ligne1 ligne2 Side Side_Top Fill Fill_X mainLoop tiq2 entr e2 ligne2 Nous
508. s que les tableaux ont une taille d termin e fix e lors de leur construction Cependant on ajoute toujours les l ments au d but d une liste et non la fin C est contraire la pratique courante quand on tient jour une liste de courses on ajoute g n ralement la prochaine course faire la fin de sa liste Toutes les listes sont construites avec les deux constructeurs de listes qu on prononce nil d apr s l anglais nil qui signifie n ant et qui provient du latin nihil qui veut dire rien et qu on prononce conse par abr viation de constructeur de 76 Listes liste est la liste vide et est l op rateur infixe qui ajoute un l ment en t te d une liste Tout comme le tableau vide la liste vide est polymorphe LS a list 0 1 2 3l int list 0 1 2 3 3 5 int list 3 1 2 3 l int list 1 2 3 Repr sentation graphique des listes Pour expliquer certaines fonctions qui manipulent des listes nous repr sentons graphiquement les calculs qu elles effectuent Pour cela nous dessinons les listes comme des peignes dont les dents contiennent les l ments de la liste Par exemple la liste trois_entiers d finie par let trois_entiers 1 2 3 trois_entiers int list 1 2 3 trois_entiers est repr sent e par le sch ma ci contre 2 Cette repr sentation en peigne a l
509. s si agressif Il nous faut donc retrouver la valeur associ e une phrase dans cette liste d association La fonction g n rale de recherche dans une liste d association s crit tr s simplement on teste si la cl a t rencontr e auquel cas on renvoie la valeur associ e sinon on cherche dans le reste de la liste Si la liste est puis e il n y a pas d espoir de trouver la valeur associ e et l on d clenche l exception constante Pas_trouv exception Pas_trouv L exception Pas_trouv est d finie let rec associ _de x function gt raise Pas_trouv cl valeur 1 gt if x cl then valeur else associ _de x l associ _de a gt a b list gt b lt fun gt 132 Le docteur associ _de Pierre Caml adresses string Domaine de Voluceau 78153 Le Chesnay Cedex associ _de Xavier Light adresses string 45 rue d Ulm 75005 Paris associ _de G rard Coq adresses Exception non rattrap e Pas_trouv Cette fonction est pr d finie en Caml sous le nom de assoc En cas d chec elle d clenche toujours une exception Dans le syst me Caml Light c est l exception Not_found signifiant pas trouv en anglais C est souvent l exception d clench e par les fonctions de recherche de la biblioth que Caml Light Des listes d association multi cl s Pour les besoins de notre programme nous devons g rer des
510. s signalerons les quelques points sp cifiques au syst me Caml Light Les lecteurs qui souhaitent consulter la documentation compl te du syst me Caml Light peuvent se reporter au Manuel de r f rence du langage Caml ou notre site Web http caml inria fr Le syst me Caml Light est distribu gratuitement et peut tre reproduit librement des fins non commerciales Pour ceux qui ont acc s au r seau Internet Caml Light est disponible sur le Web l adresse http caml inria fr L Institut National de Recherche en Informatique et en Automatique INRIA en assure galement la distri bution sur c d roms Pour obtenir ce c d rom reportez vous l encadr qui figure en page de copyright Nous encourageons le lecteur se procurer le syst me Caml Light et l installer sur sa machine suivant les instructions donn es par exemple dans le chapitre 12 du Manuel de r f rence Il pourra ainsi essayer les exemples et exp rimenter par lui m me ce qui lui facilitera grandement la lecture de ce livre Remerciements Nous tenons remercier Christian Queinnec Bernard Serpette et G rard Huet qui se sont astreints relire ce livre Val rie M nissier Morain qui a particip l illustration Tan Jacobs pour son assistance typographique et Christian Rinderknecht qui a restaur les lettrines une calligraphie anglaise du huiti me si cle Le jeu de taquin de la sec tion 11 4 est d Fran ois Rouaix l exemple de la sect
511. s sorties par bits Nous passons maintenant aux entr es sorties bit bit module esbit Fichier esbit mli value initialise unit gt unit and crire_bit out_channel gt int gt unit and lire_bit in_channel gt int and finir out_channel gt unit Les entr es sorties standard de Caml Light pr sentent les fichiers comme une suite d octets Pour voir un fichier comme une suite de bits nous allons traiter les octets comme des paquets de huit bits Arbitrairement on ordonne les bits des poids faibles vers les poids forts Ainsi l entier 143 c est dire 10001111 en binaire est vu comme la suite de huit bits 1 1 1 1 0 0 0 1 Pour transformer des op rations bit bit en op rations octet par octet nous util isons un tampon d au plus huit bits contenant l octet en cours d criture ou de lecture Le tampon est repr sent par un enregistrement deux champs mutables le champ val qui contient l octet en cours et le champ nbits qui indique le nombre de bits valides dans cet octet Fichier esbit ml type tampon mutable val int mutable nbits int let tampon val 0 nbits O let initialise tampon val lt 0 tampon nbits lt O Annexes 251 Voici par exemple la situation en cours d criture On a marqu en gris les bits qui ont t crits par la fonction crire_bit tampon nbits Tampon 11010000 tampon val Fichier TI1IT110 T0101
512. s__create_image Enfin l option Tags Tag pi ce associe chaque image le nom symbolique pi ce nous l utiliserons plus tard pour associer une action l v nement clic souris dans tous les pi ces d un coup let remplir_taquin c nx ny tx ty pi ces let trou_x ref nx 1 and trou_y ref ny 1 in let trou canvas__create_rectangle c Pixels trou_x tx Pixels ltrou_y ty Pixels tx Pixels ty in let taquin make _matrix nx ny trou in let p ref pi ces in for x 0 to nx 1 do for y O to ny 1 do match p with 1g gt O pi ce reste gt taquin x y lt canvas__create_image c Pixels x tx Pixels y ty ImagePhoto pi ce Anchor NW Tags Tag pi ce p reste done done let d placer x y let pi ce taquin x y in canvas__coords_set c pi ce Pixels trou_x tx Pixels trou_y ty canvas__coords_set c trou Pixels x tx Pixels y ty Pixels tx Pixels ty taquin trou_x trou_y lt pi ce taquin x y lt trou trou_x x trou_y y in let jouer ei let x ei ev_MouseX tx and y ei ev_MouseY ty in if x trou_x amp amp y trou_y 1 y trou_y 1 y trou_y amp amp x trou_ x 1 x trou_x 1 then d placer x y in canvas__bind c Tag pi ce ButtonPress BindSet Ev_MouseX Ev_MouseY jouer La fonction d placer ci dessus prend la pi ce en position x y et la fait gli
513. scriptif du calcul effectuer que le style fonctionnel Le style imp ratif d crit comment faire le calcul tandis que le style fonctionnel d crit quoi calculer On dit que le style fonctionnel est davantage d claratif En effet en crivant la version fonctionnelle de fact nous n avons pas d crit comment faire c est le compilateur qui a g r lui m me l encha nement des calculs 3 8 R cursivit et boucles Cette section montre qu une d finition r cursive peut cacher une boucle et qu on peut d finir une fonction r cursive localement une autre fonction Rappelons la d finition de la fonction pelle let rec pelle_aux s i if i lt string_length s then begin print_char s il print _char pelle_aux s i 1 end pelle_aux string gt int gt unit lt fun gt let pelle s pelle_aux s 0 pelle string gt unit lt fun gt Comme dans le cas des palindromes si vous estimez que la fonction auxiliaire pelle_aux n a pas d int r t en soi puisqu elle ne sert qu d finir pelle rien ne vous emp che de la d finir localement l int rieur de la fonction pelle R cursivit et boucles 51 let pelle s let rec pelle_aux s i if i lt string_length s then begin print _char s i print _ char pelle_aux s i 1 end in pelle_aux s O pelle string gt unit lt fun gt pelle Bonjour Bonjour unit Si l on
514. se liaisons autres let v rifie_tautologie proposition variables v rifie_lignes proposition variables La fonction v rifie lignes v rifie toutes les lignes de la table de v rit sans la con struire effectivement Elle prend en argument une proposition un ensemble de liaisons et la liste des variables libres de la proposition Elle lie alors les variables libres des valeurs true ou false puis value la proposition En effet la r gle gt proc de l valuation de la proposition lorsqu il n y a plus de variables lier La seconde r gle correspond au cas o il y a des variables lier elle ex cute une s quence de deux appels r cursifs v rifie lignes en liant la premi re variable rencontr e d abord true puis false Ce programme assure donc que toutes les combinaisons possibles seront envisag es et si la v rification ne d clenche jamais l exception R futation on aura effectivement prouv que la proposition s value toujours en true dans toutes les liaisons possibles de ses variables La fonction v rifie_tautologie se contente d appeler v rifie_lignes avec un ensemble de liaisons initialement vide Dans un style apparemment plus fonctionnel on crirait let rec v rifie_lignes proposition liaisons function gt value_dans liaisons proposition raise R futation liaisons var autres gt v rifie_lignes proposition var true liaisons autres a
515. se A nsi la clause lt Mot avance nombre n gt gt Av n se paraphrase en si le premier lex me du flux est le mot avance et que la fonction nombre analyse avec succ s le lex me suivant en renvoyant la valeur n alors cette clause est s lectionn e et l on renvoie l ordre Av n Pour l ordre r p te on cherche l entier indiquant le nombre de r p titions puis on cherche une liste d ordres en appelant l analyseur sp cialis liste_d ordres qui reconna t une succession d ordres entour s de crochets conform ment la syntaxe concr te que nous avons choisie L analyseur liste_d ordres attend donc un caract re crochet ouvrant Symbole puis appelle lui aussi un analyseur sp cialis dans la reconnaissance des successions d ordres enfin liste_d ordres v rifie que la liste se termine bien par un crochet fermant Symbole let rec ordre function lt Mot baisse_crayon gt gt Bc lt Mot bc gt gt Bc lt Mot l ve_crayon gt gt Lc lt Mot lc gt gt Lc lt Mot vide_ cran gt gt Ve K Mot ve gt gt Ve lt Mot avance nombre n gt gt Av n lt Mot av nombre n gt gt Av n lt Mot recule nombre n gt gt Re n lt Mot re nombre n gt gt Re n lt Mot droite nombre n gt gt Td n lt Mot td nombre n gt gt Td n lt Mot gauche nombre n
516. seule clause les deux cas __ _ gt falseet _ _ gt false Remarquons galement que le filtrage simultan ne n cessite pas les parenth ses des couples la construction permet de filtrer des expressions s par es par des virgules avec leurs filtres respectifs eux aussi s par s par des virgules match 11 12 with 0 gt true __ restel _ reste2 gt 5 7 Op rations sur les polyn mes creux Addition des polyn mes creux L addition des polyn mes creux va analyser r cursivement ses deux arguments pour en construire la somme Comme nous l avons vu dans le cas des polyn mes pleins il arrive que certains termes d un des deux polyn mes arguments n aient pas de corre spondants dans l autre parce que les polyn mes n ont pas le m me degr Dans le cas des polyn mes creux l une des listes de mon mes sera puis e avant l autre Si nous atteignons ainsi la fin de l un des polyn mes l autre constitue le r sultat cherch par exemple si l on ajoute un polyn me Py r duit une constante un autre polyn me P il faut ajouter les deux mon mes de degr 0 de P et Po mais le r sultat comprend aussi la liste des mon mes restants de P En effet les coefficients manquants du polyn me de plus bas degr correspondent des z ros implicites Dans le cas g n ral nous ajoutons les termes de m me degr ou recopions dans le r sultat final les termes qui n ont pas d
517. seur 2 int 3 D finitions locale de fonctions Rien n emp che de d finir une fonction localement bien que cela surprenne souvent les d butants en Caml Voici un exemple de fonction locale let pr d cesseur x x 1 in pr d cesseur 3 pr d cesseur 4 int 6 La fonction pr d cesseur n est d finie que pendant le calcul du produit des pr d cesseurs de 3 et 4 10 Premiers pas Les d finitions locales sont aussi utilis es dans les d finitions globales par exemple pour calculer la formule qui d finit une fonction ce qu on appelle le corps de la fonc tion D finissons par exemple la fonction pr d cesseur_carr qui retourne le carr du pr d cesseur d un nombre la fonction x x 1 Nous d finissons localement le pr d cesseur de l argument puis l levons au carr let pr d cesseur_carr x let pr d cesseur_de_x x 1 in pr d cesseur_de_x pr d cesseur_de_x pr d cesseur_carr int gt int lt fun gt pr d cesseur_carr 3 int 4 Une fonction peut aussi d finir localement une autre fonction Par exemple pour d finir la fonction puissance4 qui l ve son argument la puissance quatre il est naturel d utiliser la formule x4 x2 donc d lever au carr le carr de l argument Pour cela on d finit localement la fonction carr et on l utilise deux fois let puissance4 x let carr y y y in d finition locale d
518. si ardues Si vous n avez jamais entendu parler de polymorphisme lisez la premi re section Les sections suivantes jusqu la section 4 7 montrent le polymorphisme l uvre dans des situations pratiques Au passage section 4 3 nous ferons le point sur l alg bre de types de Caml 4 1 Notion de polymorphisme tymologiquement polymorphe signifie plusieurs poly formes morphe On em ploie ce mot par exemple en psychologie pour parler de pervers polymorphes pervers qui ne sont pas fix s sur une forme pr cise de perversion ce qui est un stade normal de d veloppement psychologique de l enfant ou bien en m decine pour des maladies qui entra nent des sympt mes variables ou des virus dont l aspect varie En informa tique ce terme d signe des objets ou des programmes qui peuvent servir sans modifi cations dans des contextes tr s divers Par exemple une fonction de tri d objets sera monomorphe si elle ne s applique qu un seul type d objets par exemple les entiers et polymorphe si elle s applique tous les types d objets qu on peut comparer pour les ranger du plus petit au plus grand Dans ce dernier cas le m me programme de tri s appliquera sans modifications des entiers comparaison lt des nombres flottants comparaison lt des flottants et des cha nes de caract res ordre du dictionnaire Du point de vue du typage cela signifie que la fonction de tri pourra tre employ e avec
519. si je vous interroge l tes vous depuis longtemps ensemble Continuez Comment votre rencontre s est elle Vous ne le pensez pas vraiment pass e ES Aimez vous cette femme 7 6 Dialogue avec l utilisateur Tirage al atoire Pour donner un peu de vari t au dialogue il nous faut videmment une fonction qui choisisse un l ment au hasard dans un tableau de valeurs possibles C est tr s simple en utilisant le g n rateur al atoire de nombres entiers fourni par Caml Dans le syst me Caml Light il s agit de la fonction random__int qui renvoie un entier compris entre 0 inclus et son argument entier exclu Il suffit donc de l appeler avec la longueur du tableau let au_choix_ dans v v random__int vect_ length v au_choix_dans a vect gt a lt fun gt Les utilitaires de salutations Un utilitaire pour crire des messages au terminal let message s print_string s print _newline message string gt unit lt fun gt message au_choix_dans salutations Diagnostic simple sans conteste vous tes parano aque Dialogue avec l utilisateur 141 unit message au_choix_dans salutations Votre cas n est pas simple et m me assez inqui tant A bient t unit Deux petites fonctions pour dire bonjour et au revoir en g rant le prix de la consulta tion let prix_ _ payer ref O prix_ _payer int ref ref 0 let b
520. soit pas ambigu aucun code d un caract re ne doit tre pr fixe du code d un autre caract re Supposons par exemple que le caract re o a pour code 0101 qui a pour pr fixe 010 le code de e Alors la suite de bits 01010111 repr sente aussi bien el que on Au contraire si aucun code n est pr fixe d un autre il y a une et une seule mani re de d couper la suite de bits contenue dans le fichier compress Pour d crire plus pr cis ment le processus de d codage il est commode de repr senter le codage sous la forme d un arbre de Huffman C est est un arbre binaire dont les feuilles sont des caract res Tout codage non ambigu est repr sent par un arbre de Huffman de la mani re suivante le code de chaque caract re est le chemin qui m ne de la racine de l arbre la feuille portant ce caract re avec la convention que 0 signifie prendre la branche de gauche et 1 signifie prendre la branche de L algorithme de Huffman 243 droite Par exemple voici l arbre de Huffman pour le codage donn page 241 nous repr sentons les arbres avec la racine en haut et les feuilles en bas comme c est l usage en informatique La d compression est tr s simple quand on dispose de l arbre de Huffman du codage On part de la racine de l arbre Si on est sur un n ud on lit le prochain bit du fichier compress et on va gauche si c est z ro et droite si c est un Quand on aboutit sur une feuille on
521. sons Nous mettons autour de cette fonction une boucle d interaction standard dans le style de celle pour le mini Logo pr sent e la section 10 3 Fichier demo ml let boucle try while true do print_string gt gt gt examine read_line done with End_of_file gt if sys__interactive then else begin boucle exit 0 end L identificateur sys__interactive est pr d fini par le syst me vaut true si le pro gramme tourne sous le syst me interactif et false si le programme tourne comme une application ind pendante Nous le testons pour viter de lancer la boucle d interaction dans le cas o ce code est ex cut depuis le syst me interactif Dans ce cas il est pr f rable de laisser l utilisateur lancer la boucle lui m me et surtout de ne pas sortir pr matur ment du syst me interactif par exit 0 quand la boucle termine Compilation du programme Il ne reste plus qu compiler les modules et les lier entre eux Voici comment faire gauche avec le compilateur ind pendant camle droite avec le syst me interactif camlc c prop mli compile rop mli caml prop mli compile prop mli camlc c prop m compile rop ml caml prop ml pile prop ml camlc c lexuniv mli compile lexuniv mli camlc c lexuniv ml compile lexuniv ml camlc c asynt mli compile asynt mli dE y li pil y li camlc c asynt m compile asynt ml l y 1 pil y 1
522. sques qui compressent au vol les donn es avant de les crire sur le disque augmentant ainsi la capacit apparente de ce dernier et m me dans l lectronique des modems qui compressent au vol en temps r el les donn es transmises sur la ligne t l phonique augmentant ainsi le d bit des transmissions En guise d exemple tr s simple d algorithme de compression mentionnons la m thode dite run length encoding qui consiste repr senter toute s quence de n fois le m me octet c par un code sp cial signifiant r p tition suivi de l octet c suivi du nombre de r p titions n Ce codage est plus compact que l original d s que n est plus grand que 4 Il est int ressant sur certains types de fichiers comme les sorties 238 Compression de fichiers pour l imprimante en informatique de gestion qui comportent de longues s quences de blancs pour aligner et de tirets pour tracer des traits Cependant il est peu pr s inefficace sur d autres types de fichiers comme les textes fran ais ou les fichiers de code ex cutable L algorithme de compression que nous utilisons dans ce chapitre l algorithme de Huffman est plus compliqu mais plus efficace car il n est pas limit une classe particuli re de donn es Sur des fichiers de texte fran ais il atteint une r duction de taille d environ 35 en moyenne Les meilleurs programmes de compression d passent 60 mais ils utilisent des algorithm
523. sser la place du trou Elle suppose que la pi ce x y est adjacente au trou Elle se contente d changer les coordonn es de la pi ce et celles du trou tout en effectuant la m me permutation dans la matrice taquin L appel canvas__bind assure que la fonction jouer est appel e chaque fois Pour aller plus loin 201 que l utilisateur clique sur un des l ments de la toile qui porte le nom symbolique pi ce c est dire sur l une des images composant les pi ces du taquin La fonction jouer d termine les coordonn es du clic souris partir de l enregistrement ei fourni par CamlTk v rifie que le clic porte bien sur une pi ce adjacente au trou et finalement d place cette pi ce let rec permutation function 0 gt 0 1 gt let n random__int list_length 1 in let l ment reste partage 1 n in l ment permutation reste and partage l n match 1 with gt failwith partage t te reste gt if n 0 then t te reste else let l ment reste partage reste n 1 in l ment t te reste Pour rendre le jeu int ressant il faut m langer initialement les pi ces La fonction permutation ci dessus effectue une permutation al atoire d une liste Elle choisit au hasard un l ment de la liste puis permute r cursivement les autres l ments de la liste et remet l l ment choisi en t te du r sultat let taquin nom_fichier nx ny let fen tre principa
524. sseur Z Z des math matiques Une contrainte de type ou annotation de type est une indication explicite du type d une expression Caml Vous pouvez si vous le souhaitez ajouter des annotations de type dans vos programmes par exemple pour aider la relecture Pour annoter un morceau de programme avec un type il suffit de mettre ce morceau de programme entre parenth ses avec son type avec la m me convention que le syst me interactif c est dire un suivi d un nom de type Caml string string Caml Nous obtenons maintenant une d finition de la fonction successeur tr s fid le celle des math matiques 12 Premiers pas let successeur int gt int function x gt x 1 successeur int gt int lt fun gt Ce style revient d finir le nom successeur comme un nom ordinaire mais dont la valeur est une fonction Cette d finition est absolument quivalente la pr c dente d finition de successeur let successeur x x 1 Fonctions anonymes plusieurs arguments Le choix entre les deux modes de d finition des fonctions est donc comme en math matiques une simple affaire de style En r gle g n rale le style let successeur x est plus concis particuli rement lorsque la fonction a plusieurs arguments puisque l autre style oblige introduire chacun des arguments par une construction function argument gt Par exemple d finir la fonction moy
525. sseur crit donc ce codage en t te du fichier compress Calculer les fr quences d apparition c est dire le nombre d occurrences des car act res dans un fichier ne pr sente aucune difficult Fichier huffman ml let fr quences entr e let fr make_vect 256 O in begin try while true do let c int_of_char input_char entr e in fr c lt fr c 1 done with End_of_ file gt end r La fonction ci dessus renvoie un tableau de 256 entiers qui donne le nombre d occurrences de chaque caract re dans le fichier entr e D terminer un codage adapt ce tableau de fr quences est plus difficile Voici un algorithme qui construit un arbre de Huffman petit petit partir d un ensemble de feuilles une par caract re apparaissant dans le fichier plus une pour la fin du fichier Chaque feuille est annot e par la fr quence d apparition du caract re correspondant 40 60 30 25 20 10 1 a e i o u y fin On choisit deux feuilles ayant la plus petite fr quence et on les regroupe en un arbre 40 60 30 25 20 11 a e i o u 0 T y fin L arbre construit re oit comme fr quence la somme des fr quences des deux lettres qu il regroupe On r p te ensuite ce proc d regroupant nouveau les deux arbres ayant la plus petite fr quence jusqu obtenir finalement un arbre unique Dans notre exemple le regroupement des arbres de fr quences 11 et 20 donne 40 60 30 25 31 a e i o
526. ssons ainsi let cons x 1 x l cons a gt a list gt a list lt fun gt Avec list_it nous crivons facilement la fonction de copie Fonctionnelles complexes sur les listes 97 list_it Ll 7 list_it cons l 4 cons JON PEN e1 5 cons JON PEN e2 He e2 X X z3 cons JON PEN En En let copie_ liste 1 list_it cons 1 l copie_liste a list gt a list lt fun gt copie_liste 1 2 3 int list 1 2 3 Cette fonction n est pas vraiment utile sauf pour copier une liste devant une autre En effet si nous voulons maintenant concat ner deux listes l et l2 mettre les deux listes bout bout il suffit de mettre lz la fin de l donc de remplacer le final de l par toute la liste l l gt concat ne li l aA pe 1 s e1 4 Z e2 TEES e2 y A ie En En l2 Il suffit donc d appeler list_it sur l avec la fonction cons et l l ment final l2 let concat ne 11 12 list_it cons 11 12 concat ne a list gt a list gt a list lt fun gt concat ne 1 2 3 4 5 6 int list 1 2 3 4 5 6 concat ne lL list_it cons l l2 ZIN FUN e1 a i JON 2N e2 e e2 N N ZN ZIN En En 12 D finitions r cursives locales Nous revenons sur le code de la fonction map pour faire la remarque suivante tant donn e une fonction f map se contente de boucler sur une liste en appliquant f C
527. stes de n importe quelle longueur donc pour toutes les listes Une application directe du principe de r currence nous permet ainsi d tablir que Si une propri t P est vraie pour une liste de longueur 0 et si d s qu elle est vraie pour une liste de longueur n elle est vraie pour une liste de longueur n 1 alors P est vraie pour des listes de n importe quelle longueur Si l on remarque qu il n existe qu une seule liste de longueur 0 la liste vide et qu une liste de longueur n 1 s obtient forc ment en rajoutant un l ment une liste de longueur n on obtient maintenant l nonc Si une propri t P est vraie pour et si d s que P est vraie pour l alors P est vraie pour z l alors P est vraie pour toutes les listes C est ce qu on appelle le principe de r currence structurelle sur les listes Remarquons que ces deux cas et x l sont justement les deux cas du filtrage d une fonction r cursive sur les listes Cela justifie nos raisonnements informels pr c dents quand nous disions un petit appel r cursif et le tour est jou ou bien que nous appelions r cursivement une fonction pas encore crite en pensant qu elle saurait bien faire toute seule Cela justifie aussi le qualificatif structurelle de ce principe de r currence puisqu on raisonne en fait sur la structure des listes Prouvons par exemple que la fonction ins re qui nous a servi de fonction auxiliaire pour le tri par
528. strat gie e2 d abord utilise moins de registres que la strat gie e1 d abord si et seulement si besoins ez est plus grand que besoins e1 La strat gie correspond donc valuer en premier celle des deux sous expressions qui a les plus grands besoins en registres Cette m thode est connue dans la litt rature sous le nom d algorithme d Ershov Compilation d une expression Nous pouvons maintenant attaquer la fonction de compilation d une expression Cette fonction prend en arguments un environnement une expression et un registre de destination et affiche sur la sortie standard le code machine qui calcule la valeur de cette expression et met le r sultat dans le registre demand La plus grande partie de la fonction compile_expr se passe de commentaire Nous utilisons toute la puissance du filtrage pour reconna tre certains cas particuliers qui correspondent directement 296 Compilation de mini Pascal des modes d adressage de la machine comme par exemple l addition d une constante ou le chargement avec un d calage constant Fichier compil ml let instr_pour_op function or gt or 4 ngn gt add non gt sub PAL gt mult n gt div n gt seq lt gt gt sne u lt gt slt gt gt sgt lt gt gle gt gt sge l tana gt wang let rec compile_expr env expr reg match expr with Constante cst
529. sultat de sa fonction argument tant donn s une fonction f et un argument x pour f double_le_r sultat_de retourne la valeur 2 f x c est dire double f x let double_le_r sultat_de f int gt int function x gt double f x double_le_r sultat_de int gt int gt int gt int lt fun gt Avec cette fonctionnelle nous pouvons nouveau calculer des fonctions Par exemple la fonction qui retourne le double du successeur de son argument function x gt 2 x 1 se calcule en appliquant la fonctionnelle double_le_r sultat_de la fonction successeur C est un calcul tout fait normal si ce n est qu il implique des fonctions et que le r sultat est en fait une fonction let double_du_successeur double_le_r sultat_de successeur double_du_successeur int gt int lt fun gt double_du_successeur 3 int 8 Typage et polymorphisme 61 La fonctionnelle sigma l occasion de la d finition des op rations sur les polyn mes nous avons vu la notation math matique X d finie par Sale i formule 0 formule 1 formule n i 0 Avec le vocabulaire des langages fonctionnels la notation X n est rien d autre qu une fonctionnelle qui prend en argument une fonction repr sentant formule et l applique successivement 0 1 n Il est tr s facile de d finir cette fonctionnelle en Caml l aide d une boucle et d un accumulateur
530. syntaxe ml camlc c envir mli camlc c envir ml camlc c typage mli camlc c typage ml camlc c compil mli camlc c compil ml camlc c cpascal ml lt R A A A EP A A A camlc o cpascal lexuniv zo syntaxe zo envir zo typage zo compil zo cpascal zo Lan ons le compilateur sur le fichier fib1 pas donn en exemple page 277 par camlrun cpascal fib1i pas depuis l interpr te de commandes ou par cpascal__compile__fichier fib1 pas depuis le syst me interactif Nous obtenons le code suivant la pr sentation a t l g rement modifi e pour tre plus lisible read store r 0 0 ri n sub sp 4 sp load r 0 O store sp O jmp Ffib ra add sp 4 sp write stop Ffib sub sp 8 sp store sp 4 ra load sp 8 r 1 n sit r 1 2 r 1 braz r 1 Li add r 0 1 r i store sp 0 r 1 fib braz r 0 L2 L1 sub sp 4 sp load sp 12 r 1 n sub r 1 1 r 1 ri n ri store sp 0 r 1 jmp Ffib ra add sp 4 sp sub sp 4 sp store sp 0 r sub sp 4 sp load sp 16 r 1 sub r 1 2 r 1 store sp 0 r jmp Ffib ra add sp 4 sp load sp 0 r 29 add sp 4 sp add r 29 r 1 r store sp 0 r 1 load sp 0 r 1 load sp 4 ra add sp 8 sp jmp ra r O 1 fib Quoique loin d tre optimal ce code n est pas de trop mauvaise facture L inefficacit la plus grossi re est la s quence add sp 4 sp sub sp 4 sp au milieu de la 304 Compilation de mini Pascal fonction fib qu
531. t gt int gt int lt fun gt La fonction fois_x est une fonctionnelle quand on l applique un argument elle fabrique une fonction qu elle renvoie en r sultat Ainsi on obtient la multiplication par 2 en appliquant fois_x 2 60 Fonctionnelles et polymorphisme let double fois_x 2 double int gt int lt fun gt double 3 int 6 On constate ainsi qu on a d fini la fonction double non pas en donnant les arguments et le corps de la fonction par la construction function mais par un calcul nous avons calcul une fonction Il n est d ailleurs m me pas n cessaire de donner un nom la fonction double pour calculer double 3 nous pouvons directement appliquer la fonction calcul e fois_x 2 la valeur 3 fois_x 2 3 int 6 La syntaxe de Caml autorise une criture encore simplifi e de cette expression sans aucune parenth se Rappelons que les conventions syntaxiques pour l application des fonctions en Caml stipulent en effet que e f x est lu comme f x e f x y est lu comme f x y En employant la premi re r gle on obtient d abord fois_x 2 3 puis en appliquant la seconde on obtient la forme la plus simple fois_x 2 3 fois_x 2 3 int 6 Fonctions dont les arguments sont des fonctions Faisons un pas de plus d finissons une fonction avec un argument fonction nel Par exemple la fonctionnelle double_le_r sultat_de qui double le r
532. t gt int ou int vect e Param tres de type comme a Les types composites sont construits avec des constructeurs de types tels que la fl che gt tant donn s deux types t et t2 le constructeur de type fl che construit le type t gt t2 qui est le type des fonctions ayant un argument du type t et rendant un r sultat du type t2 autrement dit les fonctions de t dans t2 Remarquons que le constructeur fl che est un op rateur binaire deux arguments et infixe situ entre ses arguments comme l est le symbole de l addition En revanche le constructeur de types vect est unaire puisqu partir d un unique type t il construit le type t vect Ce constructeur est postfixe c est dire plac apr s son argument Tous les constructeurs de types unaires sont postfix s en Caml Par extension les types n ayant pas d arguments int par exemple sont appel s constructeurs de types constants Les paires Il existe un autre constructeur de type binaire et infixe dont nous n avons pas encore parl le constructeur pr d fini x tant donn s deux types t et t2 la notation t t2 est donc un type C est le produit cart sien des types t et t2 Il d note le type des couples d un l ment du type t avec un l ment du type t2 En math matiques le produit cart sien de deux ensembles A et B est l ensemble des couples x y tels que x est l ment de et y l ment de B Le produit
533. t purement intuitif venait uniquement de l exp rience car on voyait bien que les compilateurs se comportaient normalement le temps de compi lation doublait approximativement quand la taille du programme doublait Le r sultat th orique est stup fiant le typage des programmes est en fait expo nentiel et m me doublement exponentiel dans notre cas Or nous savons qu un al gorithme exponentiel est catastrophiquement lent quand la taille des donn es aug mente Le caract re doublement exponentiel de l algorithme de typage devrait le ren dre compl tement inutilisable en pratique Et pourtant quelques nuances pr s cet algorithme est celui qu on utilise dans les impl mentations de Caml et l on constate vous pouvez constater qu il est assez efficace La raison en est que le comportement exponentiel pour ind niable qu il soit est extr mement pathologique La source de difficult r side dans le polymorphisme mais uniquement pour des programmes dont le polymorphisme est extraordinaire voire d raisonnable Pour montrer qu une phrase peut induire du polymorphisme de fa on exponentielle par rapport sa taille nous utiliserons la source la plus simple de polymorphisme la liste vide et la paire Nous d finissons une expression par une cascade de let in chaque tage les param tres du sch ma de type de l tage pr c dent sont dupliqu s Pour aller plus loin 361 Un tage suppl mentaire multip
534. t tre polymorphe En effet les sch mas de types de Caml sont de la forme Pour tous types la b Type ce qui signifie que tous les param tres d un sch ma de Principes de la synth se de types 343 type sont plac s en t te de ce sch ma quantification pr nexe On ne peut donc pas ex primer le type d une fonction dont l argument serait polymorphe donc li un sch ma de type comme celui d une fonction qui exigerait que son argument soit au moins aussi polymorphe que l identit Pour tout type a a a Cela explique pourquoi la fonction suivante est mal typ e let phi identit identit 1 identit oui Entr e interactive gt let phi identit identit 1 identit oui TE EN TN ee Cette expression est de type string mais est utilis e avec le type int On pourrait avoir l id e d utiliser une construction let pour cr er une variable poly morphe gale l argument de la fonction phi let phi identit let id identit in id 1 id oui Entr e interactive gt id 1 id oui SU tes Cette expression est de type string mais est utilis e avec le type int Cela ne marche pas car le type de id est l inconnue correspondant au type de l identificateur identit or cette inconnue a t cr e avant la d finition de id lors de l introduction du param tre de la fonction phi On pourrait encore d finir localement une fonction de m me s mantique
535. t re de tampon o il faut stocker le prochain caract re du mot On rappelle que la construction s n lt c rem place le n caract re de la cha ne s par le caract re c Paraphrasons lire_mot Si le premier caract re de flux est une lettre alors le stocker dans tampon l endroit d sign par position pourvu qu il reste de la place libre dans tampon et se rappeler r cursivement pour lire la suite Sinon extraire de tampon le mot lu jusqu ici et le Analyse lexicale et syntaxique 165 renvoyer L appel sub_string s O n renvoie une cha ne constitu e des n premiers caract res de s La fonction lire_lex me tant attendue se contente de regarder le premier caract re non blanc du flux et selon que c est une lettre un chiffre ou autre chose d appeler une des fonctions de lecture pr c demment d finies let lire_lex me flux saute_blancs flux match flux with lt 2 CA SZ tasari at tampon 0 lt c Mot lire_mot 1 flux lt 0 9 as c gt gt let n lire_entier int_of_char c 48 flux in begin match flux with lt gt gt Constante_flottante lire_d cimales float_of_int n 0 1 flux lt gt gt Constante_enti re n as c gt gt O end lt c gt gt Symbole c lire_lex me char stream gt lex me lt fun gt En guise de test let flux_car stream_of_string 123bonjour 45 67 flux_car char stre
536. t au point de coordonn es x y Le point courant se trouve alors l extr mit du segment qu on vient de tracer L ordre moveto x y permet de placer le point courant au point x y Un petit d tail les primitives graphiques ne sont pas accessibles directe ment il faut pr alablement pr venir le syst me qu on d sire les utiliser par la directive open graphics le di se fait partie de la directive ce n est pas le signe d invite du syst me interactif Nous consid rerons pour l instant cette directive comme une formule magique indispensable l utilisation du graphisme Nous l expliquerons plus tard dans le chapitre 10 open graphics De m me pour r aliser effectivement un dessin il faut d abord ouvrir l cran graphique par un appel la fonction pr d finie open_graph open_graph unit Dessinons maintenant un triangle rectangle isoc le dont l angle droit a pour sommet l origine du rep re moveto O 0 lineto 0 50 lineto 50 0 lineto O O unit On voit appara tre l cran le dessin en marge La biblioth que graphique de Caml est ind pendante de la machine sur laquelle tourne le syst me en ce qui concerne l ensemble des primitives graphiques En revanche le nombre de points de l cran et l ensemble des couleurs possibles sont videmment li s au mat riel Les nombres en repr sentation flottante 149 Pourquoi ne pas utiliser les pri
537. t d usage de toujours mettre une majuscule aux noms des con structeurs de type somme pour ne pas les confondre avec les noms de variables dans le filtrage Corr lativement il est recommand de toujours crire les noms de variables en minuscules Cette r gle n est pas absolue par exemple les bool ens true et false d rogent cette r gle Il est vrai que leur statut est tr s particulier puisque ce sont des constructeurs primitifs et des mots cl s du langage Formellement les types somme sont l analogue Caml de la notion math matique de somme disjointe d ensemble Nous n tudierons pas cette notion nous contentant de l id e intuitive ci dessus 6 4 Les types produit Caml offre une deuxi me classe de structures de donn es compl mentaires des types somme les types produit encore appel s enregistrements ou records en anglais D finition des types enregistrement Les enregistrements constituent une g n ralisation des n uplets Ils servent mod liser les donn es qui ont simultan ment plusieurs propri t s On les appelle donc aussi types et car ils s utilisent pour repr senter une donn e ayant telle caract ristique et telle autre caract ristique et On dresse alors la liste des car act ristiques lors de la d finition du type Chacune des caract ristiques est accompagn e de son type respectif et la liste de toutes les caract ristiques est entour e d accolades Par exemple un mon me pos
538. t destination interm diaire d place d part destination imprime_jeu nombre_de_disques gauche Imilieu ldroite hanoi hauteur 1 interm diaire d part destination end in Fonctionnelles complexes sur les listes 91 jeu 3 J appelle les tiges B et C Position de d part Je d place un disque de C lt gt l lt lt gt gt l lt gt lt lt lt gt gt gt lt lt gt gt lt lt lt gt gt gt sense sexes ss o A le IS e ll Je d place un disque de A C Je d place un disque de B A lt lt gt gt lt lt lt gt gt gt lt gt lt gt lt lt gt gt lt lt lt gt gt gt 2 Em D sue lie 222 l Je d place un disque de A B Je d place un disque de B C l lt lt gt gt lt lt lt gt gt gt lt lt gt gt lt gt lt gt lt lt lt gt gt gt Tales les amp s aSa E lie ss le LL Je d place un disque de C B Je d place un disque de C lt gt lt gt lt lt gt gt lt lt lt gt gt gt lt lt gt gt lt lt lt gt gt gt nee gan l Sz 222 le LS fee lissa 22 ESS unit Figure 5 1 R solution des tours de Hanoi 3 disques imprime J appelle les tiges A B et C imprime Position de d part imprime_jeu nombre_de_disques gauche milieu ldroite hanoi nombre_de_disques A gauche B milieu
539. t pi 4 0 atan 1 0 in pi 180 0 pi_sur_180 float 0 0174532925199 let tourne angle crayon vis e lt crayon vis e angle pi_sur_180 tourne float gt unit lt fun gt Avancer La primitive qui fait avancer le crayon se contente de calculer les d placements du crayon n cessaires selon l axe des abscisses et l axe des ordonn es dx et dy l aide des formules trigonom triques de base puis de modifier les coordonn es du crayon et enfin de d placer le crayon soit en tra ant si le crayon est baiss l aide de la primitive graphique lineto soit sans tracer de trait si le crayon est lev en utilisant alors la primitive moveto let avance d let dx d cos crayon vis e and dy d sin crayon vis e in crayon x lt crayon x dx crayon y lt crayon y dy if crayon lev then moveto round crayon x round crayon y else lineto round crayon x round crayon y avance float gt unit lt fun gt Utilitaires d initialisation du crayon Pour simplifier le travail de l utilisateur du crayon le rep re du crayon est proche de celui des math matiques l origine est au centre de l cran graphique Les coordonn es de l origine sont contenues dans deux constantes zero_x et zero_y qui valent donc respectivement size_x 2 et size_y 0 2 On initialise donc le crayon en fixant ses coordonn es au centre de l cran z ro_x z ro_y en l
540. te derni re reste une inconnue t est donc maintenant li e une autre inconnue t devient t Inconnue Inconnue Inconnue Inconnue Inconnue Inconnue La prise en compte de l quation t t3 est plus complexe puisque t pointe sur t donc que t poss de maintenant une valeur il ne faut surtout pas modifier na vement 352 Un synth tiseur de types t ce qui aurait pour effet d oublier la contrainte t t2 en faisant pointer directement t vers t3 La modification h tive de t pour lui donner la valeur de t3 produirait deux erreurs premi rement la contrainte t t2 serait oubli e au passage comme nous l avons dit de plus la contrainte induite t2 t3 ne serait pas prise en compte puisque t resterait une inconnue Traitement erron de t devient t3 gt La contrainte t t est oubli e Inconnue Inconnue Inconnue Inconnue Inconnue Inconnue Au contraire il faut suivre le pointeur qui donne la valeur de t1 ce qui conduit t2 et modifier alors t2 La modification physique correcte est donc la suivante t devient t3 Inconnue Inconnue Inconnue Inconnue Inconnue Inconnue La prise en compte de t2 int est similaire on modifie simplement la variable vers laquelle pointe t2 c est dire t3 et t est modifi e par effet t devient int i Hi El l Inconnue int Inconnue int Inconnue int La conclusion de cette discussion est qu il est g n ralement in
541. teur 1 gt imprime arguments 0 print_string print _string constructeur 2 gt print_string imprime arguments 0 print_string print_string constructeur print_string imprime arguments 1 print_string let imprime_type ty noms_des_variables l compteur_de_variables 0 imprime ty let imprime_sch ma sch ma noms_des_variables l compteur_de_variables 0 if sch ma param tres lt gt then begin print_string pour tout do_list fun var gt imprime_var var print _ string sch ma param tres print_string end imprime sch ma corps 18 7 La boucle d interaction Pour finir il ne nous reste plus qu mettre une boucle d interaction autour du synth tiseur de types La boucle est un d calque exact de celle utilis e pour l interpr te mini Caml du chapitre pr c dent Fichier typeur ml open syntaxe open types open synthese let type_arithm tique sch ma_trivial type_fl che type_produit type_int type_int type_int and type_comparaison sch ma_trivial type_fl che type_produit type_int type_int type_bool let env_initial type_ arithm tique type_arithm tique x type_arithm tique type_arithm tique type_comparaison lt gt type_comparaison lt type_comparaison gt type_comparaison Mise en uvre 359 lt type_comparaison gt
542. tf store sp d ra n profondeur_pile taille _du_mot compile_instr env2 d cl proc_corps printf load sp d ra n profondeur_pile taille_du_mot printf add sp d sp n profondeur_pile printf jmp ra r O n let compile_fonction env nom d cl let envi alloue_param tres d cl fonc_param tres env in profondeur_pile taille_du_mot let env2 list_it alloue_variable_locale d cl fonc_variables envi in let env3 alloue_variable locale nom d cl fonc_type r sultat env in printf F s n nom printf sub sp d sp n profondeur_pile printf store sp d ra n profondeur_pile taille _du_mot compile_instr env3 d cl fonc_corps printf load sp 0 r 1 n printf load sp d ra n profondeur_ pile taille_du_mot printf add sp d sp n profondeur_pile printf jmp ra r O n 302 Compilation de mini Pascal Compilation d un programme Tout est pr t pour compiler un programme complet Nous commen ons par at tribuer des adresses aux variables globales obtenant ainsi l environnement global de compilation puis compilons successivement le corps du programme les proc dures et les fonctions dans cet environnement Fichier compil ml let adresse_donn e ref 0 let alloue_variable_globale nom typ env let emplacement match typ with Integer Boolean gt Global_indirect adresse_donn e Array _ _ _ gt Global_direct adresse_donn e in adresse_
543. th cha ne 1 downto 0 do match cha ne i with n Cat ue se ec a EZEN gt ajoute_mot i 1 j j i 1 2320 done ajoute_mot 0 j extraction du dernier mot Imots divise_en_mots string gt string list lt fun gt Nous rencontrons un trait nouveau du langage les barres verticales l int rieur des filtres comme dans n Ces filtres sont des filtres plusieurs cas que l on appelle les filtres ou Ils filtrent l union des cas filtr s par leurs composants C est une simple facilit syntaxique qui vite de recopier plusieurs fois le corps de la clause Par exemple la clause 1 2 gt true est quivalente aux deux clauses 1 gt true 2 gt true 7 5 Cam lia La base de donn es Le principe de Cam lia est donc d utiliser un ensemble de phrases crites pour elle par le programmeur Le bon choix de ces phrases intervient beaucoup dans la qualit de l change Nous donnons donc ici ce que nous appelons pompeusement la base de 136 Le docteur donn es de Cam lia qui n est autre qu un ensemble de listes d association simples ou multi cl s La base de donn es comprend les listes suivantes e salutations le mot de la fin de Cam lia typiquement Ce sera long et difficile revenez me voir souvent e relances les phrases utilis es quand le programme ne sait plus quoi dire typ iquement Parlez moi enco
544. tier 900 flux_car int 900456 Pour lire les nombres flottants nous avons besoin d une fonction similaire lire_entier mais lisant les chiffres droite de la virgule et non plus gauche let rec lire _ d cimales accumulateur chelle flux match flux with lt 0 9 as c gt gt lire_ d cimales accumulateur float_of_int int_of_char c 48 chelle chelle 10 0 flux lt gt gt accumulateur lire_d cimales float gt float gt char stream gt float lt fun gt Un exemple devrait mieux nous faire comprendre qu un long discours lire_d cimales 123 4 0 01 stream_of_string 56789 float 123 456789 Derni re tape avant la lecture des lex mes la lecture d un mot Pr cisons qu un mot ici est une suite de lettres majuscules ou minuscules de A Z et de a z plus quelques lettres accentu es let tampon make_string 16 tampon string let rec lire_mot position flux match flux with KP A Z faf fzf f _ as c gt gt if position lt string_length tampon then tampon position lt c lire_mot position 1 flux I k lt gt gt sub_string tampon O min position string_length tampon lire_mot int gt char stream gt string lt fun gt La cha ne tampon sert accumuler les caract res du mot en cours de lecture Le param tre position de lire_mot est le num ro du carac
545. tilisant la fonction concat ne Suivons le d roulement de l valuation du renversement de la liste 1 2 3 rev 1 2 3 concat ne rev 2 3 1 concat ne concat ne rev 3 2 1 concat ne concat ne concat ne rev 3 2 1 concat ne concat ne concat ne 3 21 1 concat ne concat ne 3 2 1 concat ne 3 2 1 concat ne 3 2 1 3 54 91 35 5 EU 3 2 1 LUE LEA ET Il appara t que le premier l ment de la liste argument 1 a t cons une fois pour fabriquer la liste 1 Le second 2 a t cons deux fois une fois pour fabriquer la liste 2 et une fois pour obtenir la liste interm diaire 2 1 Le troisi me 3 a t cons trois fois On montre facilement que si la liste l a n l ments cet algorithme cr e une cellule de liste pour le premier l ment deux pour le second et finalement n cellules pour le dernier l ment Le nombre total de cellules cr es est donc encore la somme 1 2 3 n qui vaut n x n 1 2 l algorithme est quadratique Le ph nom ne de copie r cursive des r sultats partiels conduisant un algorithme en n est le m me que pour la fonction implose Pour am liorer cet algorithme il faut utiliser une m thode tr s g n rale pour construire directement le r sultat on ajoute un argument suppl mentaire la fonction Cet argument joue le r le d un accumulateur car on y m morise les r
546. tion try with La fonction encode fait appel un module esbit pour entr es sorties bit bit qui permet d crire sur un fichier non pas octet par octet comme les fonctions d entr e sortie usuelles mais bit par bit Nous impl menterons ce module plus tard Pour l instant voici son l interface Fichier esbit mli value initialise unit gt unit and crire_bit out_channel gt int gt unit and lire_bit in_channel gt int and finir out_channel gt unit Les fonctions crire_bit et lire_ bit permettent d crire ou de lire un bit repr sent par les entiers 0 ou 1 La fonction initialise doit tre appel e avant le premier appel crire_bit ou lire_bit La fonction finir doit tre appel e apr s le dernier appel crire_bit pour effectuer les ventuelles critures en attente La fonction encode montre un bel exemple d application partielle on it re avec la fonctionnelle do_list la fonction esbit__ crire_bit sortie obtenue par application partielle de esbit__ crire_bit la sortie courante cette fonction n est donc calcul e qu une fois avant de lancer l it ration D compression La d compression se heurte un petit probl me dans la suite de bits produite par l algorithme de compression rien ne marque les s parations entre les codes des diff rents octets Il est cependant possible de reconstituer le texte d origine condition que le codage employ ne
547. tion de Caml 371 Le socle du compilateur En g n ralisant la discussion ci dessus il appara t deux approches radicalement diff rentes de la compilation de Caml D une consiste s appuyer sur un mod le d ex cution int grant la pleine fonctionnalit dans lequel les fonctions peuvent avoir des variables libres Ce mod le d ex cution est souvent bas sur une machine virtuelle pour l ex cution du calcul Les seules optimisations que le compilateur peut alors effectuer sont des transformations de programmes de haut niveau l optimisation des fonctions elles m mes et de leur repr sentation sous forme de fermetures est difficilement exprimable L autre approche consiste exposer beaucoup plus t t la repr sentation des fonctions par des fermetures On se ram ne ainsi un langage interm diaire de type langage algorithmique classique souvent proche du langage C sur lequel le compilateur peut appliquer de nombreuses optimisations de bas niveau Cette derni re approche quoique plus complexe donne g n ralement de meilleurs r sultats les compilateurs obtenus par cette approche compilent bien ce qu il est facile de bien compiler appels des fonctions connues fonctions sans variables libres ce qui repr sente une large part des programmes qu on crit en Caml Le principal cueil qui menace cette approche est force d am liorer les cas simples de trop n gliger les cas compliqu s et d aboutir une compilatio
548. tions r cursives ainsi trait es par it rations suc cessives sont correctes si le calcul s arr te alors la valeur calcul e sera un point fixe de l quation r cursive Au pire le calcul du point fixe ne termine pas cas de let rec x x 1 ou bien choue ce qui se traduit par un r sultat ind fini cas de let rec x x Les langages paresseux ont donc de belles propri t s s mantiques mais quelques inconv nients pratiques dans la programmation de tous les jours Ils ont de plus une regrettable tendance linefficacit les arguments de fonctions sont la plupart du 336 Ex cution d un langage fonctionnel temps n cessaires la fonction on perd ainsi beaucoup de temps de calcul cr er des suspensions qu on ex cute presque aussit t Dans les compilateurs cela est temp r par des analyses de n cessit c est dire de d tection des endroits o l on peut compiler du code qui value directement un argument qui sera de toutes fa ons n cessaire dans la suite du code Ces analyses sont complexes et tr s difficiles en pr sence de fonctions d ordre sup rieur 17 6 Annexe Comme promis nous donnons ici le code de l analyseur syntaxique pour mini Caml La plus grande partie du code est une adaptation directe de l analyseur syntaxique que nous avions crit pour le langage mini Pascal chapitre 15 Fichier syntaxe ml open lexuniv let est_un_op rateur op rateurs function M
549. tique et se pr sentent sous la forme d applications ind pendantes utilisables en dehors du syst me interactif Chaque chapitre commence par une description intuitive de ce que le programme d exemple doit faire Nous introduisons ensuite les notions n cessaires pour rendre cette sp cification pr cise ainsi que les principaux algorithmes r solvant le probl me Nous impl mentons ensuite la solution en Caml sous la forme d un programme ind pendant d coup en modules Les chapitres se terminent par un paragraphe Pour aller plus loin contenant en particulier des r f rences bibliographiques l intention du lecteur qui d sire en savoir plus Les exemples proviennent de divers domaines de l informatique et supposent que le lecteur est d j vaguement familier avec les domaines concern s Notre but n est pas de fournir une introduction compl te partant de z ro ces domaines plusieurs livres n y suffiraient pas mais de montrer le langage Caml l uvre Les notions suppos es con nues font cependant partie de la culture informatique de base Par exemple le chapitre consacr la simulation d un microprocesseur suppose quelques notions l mentaires d architecture des machines et une exp rience m me minime de la programmation en assembleur De m me le chapitre consacr la compilation d un langage imp ratif simplifi suppose quelques connaissances en Pascal chaque fois nous fournirons des
550. to string_length cha ne 1 do match l tat_courant dtransitions int_of_char cha ne i with Rejet gt raise chec Vers e gt tat_courant e done l tat_courant dterminal with chec gt false Le reste du fichier determ ml est consacr la fonction de d terminisation d un automate L algorithme utilis est connu sous le nom de construction des sous ensembles subset construction Les tats de l automate d terministe correspondent des ensembles d tats de l automate de d part tous les tats qu on peut atteindre partir de l tat initial en suivant une certaine cha ne de caract res L tat initial de l automate d terministe est l ensemble des tats qu on peut attein dre en suivant la cha ne vide c est dire l tat initial de l automate de d part plus tous les tats qu on peut atteindre partir de l tat initial en suivant uniquement des epsilon transitions des transitions marqu es L tat correspondant l ensemble d tats e1 e est terminal si et seulement si un des tats e1 e est terminal Pour voir o m ne la transition sur un caract re c issue de l ensemble d tats e1 en on regarde toutes les transitions sur c issues des tats e en dans l automate initial Soient f1 fm les tats auxquels elles m nent Soient g1 gp les tats accessibles partir de f1 fm en suivant uniquement des epsilon
551. tr e type lex me stream et produit un arbre de syntaxe type ordre en sortie En composant les deux nous obtiendrons une fonction qui transforme un flux de caract res syntaxe concr te en un arbre syntaxe abstraite Nous produirons le flux de caract res initial partir d une cha ne de caract res gr ce la fonction pr d finie stream_of_string qui transforme une cha ne en le flux des caract res qui la composent 162 Syntaxe abstraite syntaxe concr te let flux_car stream_of_string Vive Caml flux_car char stream lt abstr gt Une autre mani re de construire des flux est d num rer leurs l ments l int rieur de crochets pointus lt gt let flux_ent lt 2 3 5 7 gt flux_ent int stream lt abstr gt Nous verrons plus tard d autres mani res de construire des flux Pour l instant notons simplement que chaque l ment du flux est introduit par le caract re apostrophe et que le syst me interactif ne sait pas imprimer le contenu des flux Pourquoi faire appel des flux au lieu d utiliser des listes Les flux diff rent des listes sur deux points importants qui rendent les flux mieux adapt s aux probl mes d analyse lexico syntaxique Premi re diff rence l acc s dans un flux est destructif Cela signifie que lorsqu on consulte le premier l ment d un flux cet l ment est aussit t retir du flux et remplac par l l ment suivant O
552. transformation de la cl en entier n a pas besoin d tre exacte en ce sens que deux cl s diff rentes ont sans probl me le m me entier associ Pour obtenir une bonne r partition des cl s dans les sous ensembles il faut quand m me s efforcer d viter autant que possible cette situation Dans le cas particulier o les cl s sont des cha nes de caract res cas d une grande importance pratique on propos un certain nombre de recettes pour associer rapidement un entier une cha ne avec de bonnes propri t s de r partition Voici un exemple simple de fonction de hachage sur les cha nes let hache_ cha ne taille _ table c let res ref O in for i 0 to string_length c 1 do res int_of_char c i res 128 mod taille_table done lres hache_cha ne int gt string gt int lt fun gt L id e est de faire intervenir dans le r sultat final la valeur de chacun des caract res de la cha ne pour assurer une bonne dispersion des r sultats Nous n essaierons pas de justifier la formule ci dessus dans tous ses d tails pourquoi 128 etc Nous savons donc hacher des entiers et des cha nes Le syst me Caml va beaucoup plus loin que cela il fournit une fonction de biblioth que capable d associer un en tier n importe quelle valeur Caml quel que soit son type Il s agit de la fonction hashtbl__hash de type a gt int Cette fonction est raisonnablement rapide et pro duit d
553. transitions On ajoute alors dans l automate d terministe produit une transition sur c depuis l tat D terminisation de l automate 315 e1 e vers l tat f1 fm 91 gp On r p te ce proc d jusqu ce qu il soit impossible d ajouter de nouvelles transitions titre d exemple nous allons d terminiser l automate produit pour l expression toto par la fonction expr_vers_automate DADERDADIDDLD ADO DADIO Les tats sont num rot s de 1 12 pour tre rep r s plus facilement partir de l tat initial 1 on peut atteindre 2 4 et 5 par epsilon transitions L tat initial de l automate d terministe est donc 1 2 4 5 Il est non terminal 1 2 4 5 Il y a deux types de transitions issues de cet tat la transition sur t et les transitions sur un caract re autre que t Sur t 2 m ne 3 5 m ne 6 2 et 4 ne m nent rien partir de 3 on peut atteindre 2 4 5 par epsilon transitions partir de 6 on peut atteindre 7 par epsilon transition On ajoute donc une transition sur t issue de 1 2 4 5 et menant 2 3 4 5 6 7 De m me sur un caract re autre que t 2 m ne 3 et 2 4 5 ne m nent rien partir de 3 on peut atteindre 2 4 5 par epsilon transitions On ajoute donc des transitions sur tous les caract res sauf t transitions issues de 1 2 4 5 et menant 2 3 4 5 pas t En r p tant ce raisonnement jusqu plus soif on finit par o
554. tribuer des codes de longueur variable aux caract res en faisant en sorte que les caract res les plus fr quents re oivent des codes courts moins de huit bits et les caract res les plus rares des codes longs ventuellement plus de huit bits Par exemple le codage suivant conviendrait pour du texte crit en fran ais espace 110 t 1000 e 010 i 0010 s 1001 r 0001 a 0011 u 11101 n 0111 1 10111 pour les lettres les plus fr quentes et ainsi de suite jusqu aux lettres les plus rares X 11100110111100111 Y 011010001010000010 Z 011010001010000001 Compression Compresser un fichier consiste remplacer chaque octet du fichier par la suite de bits qui l encode puis crire octet par octet la suite de bits obtenus Avec le codage ci dessus le mot utile suivi d un espace est transform en la suite de bits 11101 1000 0010 10111 010 110 c est dire en les trois octets 55 11101100 168 00010101 et 107 11010110 On a choisi arbitrairement de lire les nombres binaires avec le bit de poids faible gauche et le bit de poids fort droite Le texte compress occupe trois octets au lieu de six pour le texte d origine Pour viter les probl mes qui se posent quand le dernier octet du fichier compress n est pas enti rement rempli on convient de terminer tous les fichiers compress s par un code sp cial de fin Ce code n apparaissant qu une fois pour tout le fichier il peut tre choisi assez long Voic
555. true do print_string flush std_out try match lire_phrase flux_d entr e with Expression expr gt let r s value lenv_global expr in print_string imprime_valeur r s Mise en uvre 333 print_newline D finition d f gt let nouvel_env value _ d finition lenv_global d f in begin match nouvel_env with nom val _ gt print_string nom print_string imprime valeur val print_newline end env_global nouvel_env with Parse_error Parse_failure gt print_string Erreur de syntaxe print _newline Erreur msg gt print_string Erreur l valuation print_string msg print_newline done if sys__interactive then else boucle 17 4 Mise en uvre L interpr te mini Caml se compile comme suit camlc c syntaxe mli camlc c eval mli camlc c eval ml camlc c lexuniv mli camlc c lexuniv ml camlc c syntaxe ml camlc c interprete ml camlc o interprete lexuniv zo syntaxe zo eval zo interprete zo Apr s lancement par camlrun interprete ou interprete__boucle il ne reste plus qu essayer quelques unes de nos fonctions pr f r es let rec fib function n gt match n lt 2 with true gt 1 false gt fib n 1 fib n 2 fib lt fun gt fib 10 89 let map function f gt let rec maprec function gt D x 1 gt f x maprec 1 in maprec map lt fun gt
556. tures en propor tions gales et qu on identifie par les peintures qui les composent Nous introduisons donc un nouveau constructeur M lange avec pour argument un couple de peintures Notre type devient type peinture Bleu Blanc Rouge Num ro of int M lange of peinture peinture Le type peinture est d fini let m li M lange Bleu Blanc m li peinture M lange Bleu Blanc let m l2 M lange Num ro 0 Rouge m l2 peinture M lange Num ro 0 Rouge Remarquez que le type peinture est devenu r cursif puisqu il intervient dans sa propre d finition Ainsi on peut m langer n importe quelles peintures et en particulier faire des m langes de plus de deux peintures let m l3 M lange m l1 m 12 m l3 peinture M lange M lange Bleu Blanc M lange Num ro 0 Rouge Le filtrage sur le type peinture ne pose pas de probl mes let rec contient _du_bleu function Bleu gt true M lange pi p2 gt contient _du_bleu pi contient _du_bleu p2 _ gt false contient_du_bleu peinture gt bool lt fun gt contient _du_bleu m l3 bool true Types sommes labor s 115 La d finition du type peinture quoique r cursive conserve tout de m me un sens parce qu il existe des cas de base pour arr ter la r cursion C est tout fait analogue aux d finitions de fonctions r cursives qui pr sentent des cas d arr t simples Le
557. type ordre fonction ex cute_ordre alex l analyseur lexical type lex me fonction lire_lex me asynt l analyseur syntaxique fonction analyse_programme logo le programme principal la boucle d interaction chaque module correspond un fichier source qui a le m me nom que le module avec l extension ml Par exemple les fonctions du module crayon sont d finies dans le module crayon ml Le contenu de ces fichiers est r sum figure 10 1 Noms ext rieurs La figure 10 1 montre que nous avons ajout chaque module des lignes de la forme open plus un nom de module Ces lignes indiquent d o proviennent les noms ext rieurs qu on utilise dans le fichier sans les y avoir d finis Gr ce ces indications le compilateur sait o aller chercher le type et le code compil de ces noms ext rieurs Il y a deux mani res de faire r f rence un identificateur ext rieur L une est d utiliser des noms qualifi s de la forme nom du module d origine suivi de deux caract res soulign suivi du nom de l identificateur Ainsi asynt__analyse_ programme signifie l identificateur analyse_programme d fini dans le module asynt L autre mani re d acc der des identificateurs ext rieurs est d introduire des direc tives open module Cette directive indique au compilateur qu on veut ouvrir to open en anglais le module donn en argument Plus pr cis ment cette directive dit que si l o
558. type_fl che type_simple gt type_simple gt type_simple and type_produit type_simple gt type_simple gt type_simple and type_liste type_simple gt type_simple value nouvelle_inconnue unit gt type_simple and unifie type_simple gt type_simple gt unit and g n ralisation type_simple gt sch ma_de_types and sp cialisation sch ma_de_types gt type_simple and sch ma_trivial type_simple gt sch ma_de_types and d but_de_d finition unit gt unit and fin_de_d finition unit gt unit exception Conflit of type_simple type_simple and Circularit of type_simple type_simple value imprime_type type_simple gt unit L algorithme de synth se de types 345 and imprime_sch ma sch ma_de_types gt unit Voici une br ve description des op rations du module types Nous donnerons plus de d tails par la suite mais pour l instant il est inutile d en savoir plus type_int type_bool les constantes de types int et bool type_fl che t t2 renvoie la repr sentation du type t gt to type_produit t t2 renvoie la repr sentation du type t t2 type_liste t renvoie la repr sentation du type t list nouvelle_inconnue cr e une nouvelle inconnue de typage unifie t t2 enregistre l quation t t2 et la r sout compte tenu des quations d j enregistr es Conflit Circularit exceptions d clench es par unifie lorsqu on lui donne une quation qui n a pas de so
559. ucteur d finition de constructeur identificateur identificateur of type Les exceptions comme moyen de calcul Les exceptions ne servent pas seulement g rer les erreurs elles sont aussi utilis es pour calculer Dans ce cas la valeur exceptionnelle transporte un r sultat ou bien signale un v nement attendu titre d monstratif nous d finissons la fonction caract re _dans_cha ne qui teste l appartenance d un caract re une cha ne et dont nous avons besoin pour impl menter Cam lia On pourrait videmment crire cette fonction l aide d une fonction r cursive locale let caract re _dans_cha ne cha ne car let rec car_dans_cha ne i i lt string_length cha ne amp amp cha ne i car car_dans_cha ne i 1 in car_dans_cha ne O caract re_dans_cha ne string gt char gt bool lt fun gt Cependant cette fonction r cursive code videmment une boucle nous pr f rons donc l crire avec une boucle On parcourt donc la cha ne argument l aide d une boucle for en recherchant le caract re donn Cependant que faire si le caract re est trouv Il faut arr ter la boucle et signaler sa pr sence Ce comportement revient d clencher une exception Nous d finissons donc l exception Trouv Et nous surveillons la boucle de recherche si l exception est d clench e la fonction renvoie true En revanche si la boucle se termine normalement c est que le
560. ue beaucoup de programmes Caml n utilisent pas la pleine fonctionnalit et sont en fait tr s proches de programmes Pascal tout au moins du point de vue de la compilation Si le compilateur s efforce d adopter pour ces programmes la m me strat gie qu un compilateur Pascal il fera du bon travail Par exemple dans les programmes courants la plupart des appels de fonctions con cernent des fonctions connues du compilateur et dans ce cas le compilateur produit du code plus efficace en passant tous les arguments d un seul coup et en engendrant un appel direct au code de la fonction De la m me fa on on n est pas oblig de fabri quer syst matiquement une fermeture pour toutes les fonctions d un programme car beaucoup de fonctions restent locales au module ou la phrase qui les d finit Le compilateur doit s efforcer de d tecter ces cas Remarquez cependant qu on ne peut pas liminer la fabrication dynamique de fermetures au cours de l ex cution pensez let g function x gt function y gt x y puis let h g 3 ou encore des fonctions dont la valeur est crite dans une structure de donn es Lorsqu il est contraint et forc d allouer une fermeture le compilateur a le choix en tre plusieurs strat gies d allocation des environnements de fermetures La premi re est le partage maximal des environnements l environnement d ex cution du programme est constamment maintenu l ex cution comme pour
561. ues et les v rifiera automatiquement chaque composition de fonctions Consid rons l exemple d cole du successeur de la longueur d une cha ne de caract res d abord sous forme graphique puis en Caml longueur_plus_un string int int 72 Fonctionnelles et polymorphisme let longueur_plus_un compose successeur string_length longueur_plus_un string gt int lt fun gt longueur_plus_un OK int 3 La composition de ces deux fonctions dans l ordre inverse n a pas de sens ce que le contr leur de types signale compose string_length successeur Entr e interactive gt compose string_length successeur D mennaanane Cette expression est de type int gt int mais est utilis e avec le type int gt string La fonctionnelle de curryfication Nous allons d finir une fonctionnelle curry pour obtenir automatiquement la ver sion curryfi e d une fonction non curryfi e deux arguments Notre fonctionnelle pren dra donc en argument une fonction f dont l argument est une paire x y et rendra en r sultat une fonction deux arguments qui est donc de la forme function x gt function y gt rendant le m me r sultat que f On obtient donc let curry f function x gt function y gt m me r sultat que f pour x et y Puisque le m me r sultat que f pour x et y n est autre que f x y on a donc simplement let curry f function x gt functi
562. uisons les notions d automates et d expressions rationnelles qui sont un des fondements de l informatique Nous montrons comment manipuler en Caml des graphes et plus g n ralement des structures de donn es qui contiennent des cycles 16 1 Les motifs Dans le cas le plus simple le motif que l on recherche dans un fichier est une suite de caract res pr cise Par exemple en Unix la commande grep xop dictionnaire affiche toutes les lignes du fichier dictionnaire qui contiennent la cha ne xop Pour plus de souplesse dans la recherche on autorise des jokers dans la cha ne chercher Ainsi grep c r dictionnaire affiche toutes les lignes contenant un c suivi d une lettre quelconque puis d un r de m me grep c r affiche toutes les lignes contenant un c puis un r s par s par un nombre quelconques de lettres Nous utiliserons une famille encore plus g n rale de motifs connus sous le nom d expressions rationnelles en anglais regular expressions Une expression rationnelle est ou bien e un caract re c e l expression vide not e e une alternative e1 e2 o e1 et e2 sont elles m mes deux expressions rationnelles e une s quence 1 2 o e1 et e2 sont elles m mes deux expressions rationnelles e une r p tition ex o e est une expression rationnelle 306 Recherche de motifs dans un texte Pour chaque expression rationnelle on d finit les cha nes de caract res reconnues par cette expression ratio
563. ujours la forme la plus simple sans parenth ses En revanche on ne peut absolument pas grouper les arguments 2 et 6 l int rieur de parenth ses moyenne 2 6 est erron Cela signifierait en effet qu on d sire ap pliquer moyenne un seul argument 2 6 Qui plus est cela voudrait dire qu on tente d appliquer le nombre 2 au nombre 6 Des expressions construites sur le mod le moyenne 2 6 c est dire plus g n ralement du genre f g y ont pourtant un sens Consid rez par exemple le calcul du successeur du successeur de 1 On crit naturellement successeur successeur 1 int 3 Mais si l on te les parenth ses on crit successeur successeur 1 et cela signifie maintenant que nous voulons appliquer la fonction successeur deux arguments le premier argument serait la fonction successeur elle m me et le second argument serait 1 Cependant la fonction successeur n admet qu un seul argument si nous retirons les parenth ses sciemment ou par inadvertance Caml nous indique donc une erreur Diagrammes syntaxiques 17 successeur successeur 1 Entr e interactive gt successeur successeur 1 D nana aaaane Cette expression est de type int gt int mais est utilis e avec le type int Le message indique en effet que l expression soulign e successeur est une fonction de type int gt int elle ne peut pas tre utilis e comme un argument entier Retenons de toute fa on que
564. uler des identit s remarquables Nous serons par exemple en mesure d tablir par programme la formule x 1 x 2x 1 En termes sa vants nous ferons du calcul formel sur des polyn mes une ind termin e Si vous savez d j qu il y a autre chose dans la vie que la programmation fonctionnelle et que vous connaissez les boucles for et while vous pouvez sauter ce chapitre 3 1 La programmation imp rative Jusqu pr sent nous avons crit de petits programmes dans un sous ensemble de Caml la partie d clarative la plus proche des math matiques Nous avons toujours d fini des fonctions qui retournaient le r sultat que nous voulions calculer Ces fonc tions calculent le r sultat souhait au sens des calculs math matiques c est dire par simplifications successives d une expression Ce style de programmation l aide de fonctions s appelle la programmation fonctionnelle Une autre fa on de calculer consiste consid rer qu un calcul est un processus volutif o le temps a son importance Il s agit de modifier un tat l ordinateur com mence l ex cution du programme dans un certain tat initial que l ex cution du pro gramme modifie jusqu parvenir un tat final qui contient le r sultat voulu On change l tat courant par modification du contenu de la m moire de l ordinateur l aide d affectations ou encore par interaction avec le monde ext rieur interrogation d
565. uli rement simple il suffit d avancer quatre fois de la longueur du c t en tournant chaque fois d un angle droit let carr c for i 1 to 4 do avance c tourne 90 0 done carr float gt unit lt fun gt Nous initialisons le crayon puis lan ons le dessin vide_ cran carr 75 0 unit Dessinons maintenant les ailes d un moulin let aile c avance c carr c avance c aile float gt unit lt fun gt Premiers dessins 153 let ailes c tourne 45 0 for i 1 to 4 do aile c tourne 90 0 done ailes float gt unit lt fun gt vide_ cran ailes 25 0 unit Une simili rosace s obtient en faisant tourner un carr sur son coin inf rieur gauche vide_ cran for i 1 to 36 do carr 40 0 tourne 10 0 done unit Un cercle se dessine simplement petits pas en avan ant un peu d un point par exemple et tournant un peu d un degr pendant 360 degr s let rond for i O to 360 do avance 1 0 tourne 1 0 done rond unit gt unit lt fun gt vide_ cran rond unit Il n est pas difficile de d finir une proc dure g n rale pour dessiner un cercle de rayon R ou des portions de cercle d un rayon et d un angle donn s On doit maintenant calculer le pas du crayon mais puisque le crayon parcourt la circonf rence compl te du cercle en 360 pas on a 2 x m x R 360 x pas
566. unction gt x reste gt Le cas de la liste vide est simple une liste vide est videmment tri e on renvoie donc la liste vide let tri_par_insertion function g gt O x reste gt Dans l autre cas on va commencer par trier le reste de la liste C est d j possible bien que nous n ayons pas encore crit notre fonction de tri il suffit d appeler r cursivement la fonction tri_par_insertion que nous sommes justement en train d crire let rec tri_par_insertion function g gt O x reste gt tri_par_insertion reste Il nous suffit maintenant de mettre l l ment x la bonne place dans le reste maintenant tri de la liste C est facile on se contente d appeler la fonction ins re Nous obtenons let rec tri_par_insertion function g gt O x reste gt ins re x tri_par_insertion reste La fonction de tri est termin e Il nous reste crire la fonction ins re Par le m me raisonnement que ci dessus on commence par en crire le squelette let ins re l ment function OD gt x reste gt Le cas de la liste vide est encore une fois simple il suffit de retourner une liste r duite l l ment qu on souhaite ins rer let ins re l ment function O gt l ment x reste gt Dans l autre cas la liste o l on veut ins rer l ment commence par x Si l ment est plus
567. une affaire de go t personnel de style et d exp rience Nous pr f rons la version avec exception car elle se g n ralise plus facilement plusieurs v nements attendus dans la boucle Au surplus la boucle s arr te instantan ment quand l v nement arrive et c est tr s souvent un comportement algorithmiquement n cessaire du programme 7 3 Fonctions de recherche dans les listes Les r ponses toutes faites de Cam lia sont stock es dans des listes d une forme particuli re les listes d association qui associent des r ponses certains mots de la phrase du patient Appartenance d un l ment une liste Nous commen ons par crire la fonction membre qui d termine si son premier ar gument est l ment d une liste donn e en second argument Travaillant sur des listes la fonction membre doit par cons quent envisager les deux cas possibles de listes d o le squelette de fonction let membre e function OD gt x reste gt Le cas de la liste vide est simple l l ment rechercher n appara t certainement pas dans la liste let membre e function gt false x reste gt Fonctions de recherche dans les listes 131 Dans le cas g n ral il faut tester si e est gal la t te de la liste x sinon interroger r cursivement le reste de la liste On obtient donc let rec membre elem function gt false x reste gt x elem memb
568. ur un tat non terminal ou si on reste bloqu en cours de route parce qu un tat n a pas de transition sur le prochain caract re alors la cha ne n est pas reconnue La th orie des automates montre que pour tout automate il existe un automate d terministe qui reconna t exactement les m mes cha nes Nous allons donc commencer par transformer l automate pr c demment construit en un automate d terministe puis utiliser cet automate d terministe pour d cider si une cha ne est reconnue ou pas Voici l interface du module determ qui fournit ces deux fonctions 314 Recherche de motifs dans un texte Fichier determ mli type tat mutable dtransitions transition vect dterminal bool and transition Vers of tat Rejet value d terminise auto__ tat gt determ__ tat and reconna t determ__ tat gt string gt bool Un tat d un automate d terministe est repr sent par un enregistrement deux champs un bool en dterminal indiquant si l tat est terminal ou non et un tableau dtransitions 256 cases une par caract re du jeu ASCII Le constructeur Vers indique la pr sence d une transition vers l tat indiqu le constructeur Rejet indique l absence de transition L impl mentation de la fonction reconna t est tr s simple Fichier determ ml exception Echec let reconna t automate cha ne let tat_courant ref automate in try for i 0
569. ure ses variables et son corps Puis on calcule l environnement dans lequel le corps de la proc dure doit tre valu c est l environnement env_pour_corps Il est obtenu en liant les param tres de la proc dure aux valeurs des arguments avec lesquels la proc dure a t appel e La fonction locale augmente_env parcourt donc simul tan ment la liste des param tres de la proc dure et la liste des arguments Si ces listes sont vides proc dure sans param tre ou liste de param tres compl tement trait e le nouvel environnement est l environnement courant env Sinon il suffit de calculer la liaison du premier param tre de la proc dure variable la valeur du premier argument l expression expr On ajoute donc la paire variable valeur _expr env Ajout des proc dures 173 expr la liste des autres liaisons qu on obtient en appelant r cursivement la fonction augmente_env sur le reste des param tres et le reste des valeurs des arguments les expressions exprs videmment si la liste des param tres et la liste des expressions ne s puisent pas en m me temps c est qu il y a une erreur sur le nombre d arguments fournis lors de l appel de la proc dure on choue alors avec un message d erreur Il ne reste plus ensuite qu ex cuter la liste des ordres du corps de la proc dure dans ce nouvel environnement en surveillant le d clenchement de l exception Stop Remar quez encore une fois l application parti
570. us calculons la somme des polyn mes X 3X et 3 2X 5X imprime_polyn me_creux ajoute_polyn mes_creux 1 2 3 4 3 0 2 2 5 10 3 3x 2 3x 4 5x 10 unit Multiplication des polyn mes creux La multiplication op re galement par filtrage simultan de ses deux arguments Dans le cas o l un des polyn mes est puis il n y a plus de multiplication faire En ef fet les mon mes manquants ont implicitement des coefficients nuls donc les multiplica tions produiront toujours des coefficients nuls En ce cas le r sultat est donc la liste vide Sinon on applique simplement la r gle habituelle de distributivit de la multiplication par rapport l addition Voyons soit m1 le premier mon me de P et reste les autres mon mes de P On a P m restei donc Pi x P2 m1 X P2 reste x P2 Si l on ap pelle notre fonction multiplie_polyn mes_creux alors reste x P gt correspond l appel r cursif multiplie_polyn mes_creux restel p2 Quant lexpression m1 x P2 c est un cas plus simple o l on multiplie un polyn me par un mon me Nous le traiterons par la fonction auxiliaire multiplie_par_mon me_ creux L expression m1 x Pz reste x Pz s crit donc ajoute_polyn mes_creux multiplie_par_mon me_ creux m1 p2 multiplie_polyn mes_ creux restel p2 Il reste d finir multiplie_par_mon me_creux Si m est le mon me et P le polyn me il suffit de multiplier chaque
571. us forme de table de hachage nous divisons cette liste en dix listes d association suivant le dernier chiffre du num ro let table _des_sous_ensembles I x O 0139635570 Nelly x 1 x 11 police 0139635511 standard x 2 x 0139635202 Xavier x 3 3613 T l tel 1 x 4 x 7234864 Xavier 5 3615 T l tel 3 6 x 16 pompiers x 7 D x 8 0139635198 Pierre 9 I Pour trouver le sous ensemble dans lequel chercher une cl on cherche son num ro en hachant la cl puis on extrait du tableau le sous ensemble concern Pour chercher l associ d une cl on utilise simplement assoc sur le sous ensemble correspondant la cl let sous_ensemble_ de cl let num ro_du_sous_ensemble hache cl in table_des_sous_ensembles num ro_du_sous_ensemble sous_ensemble_de int gt int string list lt fun gt let associ _ de cl assoc cl sous_ensemble_de cl associ _de int gt string lt fun gt associ _de 3615 string T l tel 3 associ _de 911 Exception non rattrap e Not_found Chaque appel associ _de finit donc par appeler la fonction assoc mais sur des listes d association beaucoup plus petites que la liste repr sentant tout l annuaire un et deux l ments respectivement au lieu de neuf Dans certains cas on tombe m me imm diatement sur un sous ensemble vide par exem
572. us tard dans des contraintes de types engendr es par le reste du programme Consid rons ce programme function x gt let y x in x y Juste avant de typer la partie in les quations de typage sont type de x t type de y t et il serait incorrect de conclure que y a le type Pour tout a la puisque le reste du programme va r v ler que tj int En revanche on d montre que toutes les inconnues qui ont t introduites pendant le typage de la d finition et qui sont toujours inconnues la fin du typage de la d finition ne seront pas modifi es plus tard par ajout de contraintes suppl mentaires nous sommes donc fond s mettre un pour tout devant ces inconnues les transformant en param tres du sch ma de type Dans le synth tiseur de types nous aurons donc un m canisme pour retrouver facilement toutes les inconnues introduites pendant le typage d une d finition L id e est simplement d associer un ge aux inconnues refl tant la date laquelle elles ont t introduites Remarquons que les d finitions d identificateurs par let sont les seules construc tions qui engendrent des sch mas de type c est pourquoi on dit souvent qu en Caml seul le let donne du polymorphisme En particulier les arguments de fonctions n ont jamais de type polymorphe Ceci vient directement de la structure des types ma nipul s en Caml il est impossible d exprimer avec ces types qu un argument de fonc tion doi
573. utes les d finitions de fonctions sont valu es en s quence sans effets visibles puis la phrase ci dessus est ex cut e La boucle infinie while true do affiche un signe d invite puis lit une phrase sur le flux des caract res entr s au clavier Si le premier mot est fin on sort du programme en rendant imm diatement la main l aide de la fonction pr d finie exit Sinon on ex cute la phrase lue et on refait un tour de boucle pour lire la suivante 10 4 Programmes en plusieurs modules Plut t que de mettre tout le texte d un programme dans un seul fichier il est pr f rable de le d couper en plusieurs petits fichiers que l on compile un par un Non seulement l dition et la recompilation sont facilit es mais surtout on s autorise alors la r utilisation de certains morceaux du programme dans d autres programmes Par exemple les fonctions sur le crayon lectronique avance sont susceptibles d tre 184 Programmes ind pendants et modules utilis es dans bien d autres programmes que notre syst me mini Logo On appelle mod ules ces morceaux de programme suffisamment autonomes pour tre ventuellement r utilis s plus tard et programmation modulaire le style de programmation consistant d couper syst matiquement les programmes en modules Nous allons donc d couper le mini Logo en cinq modules crayon le crayon lectronique fonctions avance tourne langage le langage de commandes
574. uton Le composant p re est le composant l int rieur duquel le bouton doit appara tre ici c est la fen tre principale de l application telle que renvoy e par openTk Quant aux options nous en donnons ici deux Text Pressez moi qui indique que le bouton doit porter l tiquette Pressez moi et Command action qui associe la fonction Caml action aux clics sur le bouton Le programme appelle ensuite la fonction pack emballer en anglais pour ef fectuer le placement des composants dans les fen tres La fonction pack prend une liste de composants et une liste d options expliquant comment placer les composants les uns par rapport aux autres l un au dessus de l autre ou l un c t de l autre avec ou sans espace entre les composants etc Ici le placement est tr s simple puisqu il n y a qu un seul composant dans notre interface Enfin la fonction mainLoop est appel e Celle ci ouvre la fen tre l cran affiche le bouton dedans et appelle la fonction action chaque fois que l utilisateur clique sur le bouton La fonction mainLoop ne rend la main que lorsque l utilisateur a ferm la fen tre CamlTk ou bien interrompu le programme 11 2 Relier des composants entre eux Passons maintenant un exemple plus int ressant Rouge qui introduit deux nouveaux types de composants EE les glissi res et les cadres et montre comment coupler entre eux les tats de plusieurs composants
575. v 1 2 3 int list 3 2 1 Cette version peu commune de rev est galement lin aire et r cursive terminale En conclusion on constate que map et do_list sont des versions sp cialis es d it rateurs plus g n raux Ces fonctions gardent cependant leur int r t car elles sont simples employer et comprendre Du point de vue purement calculatoire it_list et list_it sont un tant soit peu redondants mais ils se distinguent lorsque les fonctions qu ont leur applique produisent des effets On constate une fois de plus que les effets compliquent les choses car ils permettent de distinguer plus finement le comportement d algorithmes math matiquement quivalents On peut s en r jouir ou en avoir peur la recherche de l it rateur unique 107 6 Les structures de donn es O l on apprend m langer les torchons et les serviettes pour d finir le linge de maison N CAML les types de donn es comprennent principalement les types somme et les types produit c est dire les types ou et les types et encore appel s les num rations g n ralis es et les enregistrements ou plus techniquement encore l union disjointe et les produits champs nomm s Dans ce chapitre nous in troduisons ces diff rents types de donn es et les montrons l uvre sur le probl me de la repr sentation efficace des polyn mes 6 1 Polyn mes pleins et polyn mes creux Nous avons vu par deux fois
576. vent pas tre locales une autre proc dure ou fonction Les param tres sont pass s par valeur pour les entiers et les bool ens et par r f rence pour les tableaux Derni re diff rence majeure par rapport Pascal les proc dures et les fonctions sont consid r es comme mutuellement r cursives on peut donc appeler une proc dure avant de l avoir d finie comme en Modula 2 titre d exemple voici deux programmes mini Pascal qui calculent la fonction de Fibonacci de mani re plus ou moins na ve Fichier fib1 pas program fibonacci var n integer function fib n integer integer begin if n lt 2 then fib 1 else fib fib n 1 fib n 2 end begin read n write fib n 278 Compilation de mini Pascal end Fichier fib2 pas program fibonacci var fib array 0 100 of integer var n integer var i integer begin read n fib O 1 fibl1 1 i 2 while i lt n do begin fiblil fibli 1 fibli 2 i i 1 end write fibln l end La syntaxe abstraite c est dire la repr sentation interne des programmes crits dans ce langage est structur e en plusieurs niveaux correspondant chacun un type concret Caml Niveau Type Caml Exemple Constantes constante true Expressions expression x i Instructions instruction x x 1 Expressions de type expr_type array 1 10 of integer D clarations de proc dures d cl_proc procedure p x
577. voir t claire Dites tout de suite que je suis La communication est difficile non g teuse Ah les hommes Ils ne comprennent rien J Cessez de poser des questions let r ponses_aux_petits_mots N auriez vous pas des probl mes me C nest comprendre Pas du tout C non Vraiment pas I C est vite dit Pourquoi pas l Pourriez vous pr ciser jamais Je note c est non l Ne dites jamais jamais Mais encore Jamais me semble un peu fort non La r ponse n est pas si simple non Jamais Vous tes vraiment tr s s r de vous C non Ne vous arrive t il pas de douter de I En tes vous s r vous m me Pourquoi pas Ne r pondez pas toujours oui ou non Que diriez vous dans le cas contraire Syndr me du yes no Expliquez vous que C est une opinion d fendable diable Je saurai au moins votre opinion Au moins vous ne souffrez pas de diarrh e l dessus verbale LC rien Comment pouvez vous tre si s r de l Rien du tout vous Pourquoi pas si Que diriez vous dans le cas contraire I Si b mol Voil qui est franc D accord d accord Au moins c est clair Mouais je m en doutais un peu M me pas un petit peu figurez vous Rien est un peu exag r non Expliquez vous si ne me suffit pas pourquoi R ponse trop laco
578. voulions justement pas avoir besoin d crire partir du format d entr e qui nous convient Dans la section suivante nous allons voir en d tails les analyseurs syntaxique et lexical du langage graphique 9 6 Analyse lexicale et syntaxique Les flux Pour programmer l analyse lexicale et l analyse syntaxique du langage nous al lons utiliser une structure de donn es Caml que nous n avons pas encore vue les flux streams en anglais Tout comme les listes les flux sont des suites de valeurs du m me type Le type d un flux est t stream o t est le type des l ments du flux Ainsi un flux d entiers a le type int stream de la m me mani re qu une liste d entiers a le type int list Nous programmerons l analyseur lexical comme une fonction qui prend un flux de caract res en entr e type char stream et produit un flux de lex mes en sortie type lex me stream Nos lex mes comprennent des entiers des flottants des mots simples suites de caract res commen ant par une lettre et des symboles c est dire des caract res qui ne sont ni chiffres ni lettres par exemple le point Les lex mes sont donc d crits par le type concret suivant type lex me Mot of string Symbole of char Constante_enti re of int Constante_flottante of float Le type lex me est d fini De m me l analyseur syntaxique se pr sentera sous la forme d une fonction qui prend un flux de lex mes en en
579. x 1 Les liaisons sont mises en vidence dans ce sch ma let x 1 in let X 1 and y Q 2 in On retiendra que dans une d finition Caml y compris une d finition simultan e Un nom fait toujours r f rence une d finition pr alable La construction let rec Ceci pose videmment probl me pour d finir des fonctions r cursives nous ne pou vons utiliser une d finition introduite par un let cause de la r gle de port e statique En effet si nous crivons let f f l occurrence de f dans l expression d finissante f ne correspond pas au nom f que nous sommes en train de d finir en particulier parce que f n est pas encore d finie mais doit correspondre une d finition pr c dente de f Un petit sch ma vaut mieux qu un long discours la liaison de f s tablit vers le pass let f Ee Ein C est pourquoi une simple construction let ne permet pas de d finir une fonction r cursive 22 R cursivit let factorielle n if n 0 then 1 else n factorielle n 1 Entr e interactive gt let factorielle n if n O then 1 else n factorielle n 1 Le CS M EN CT ee L identificateur factorielle n est pas d fini En bref une liaison let n est pas r cursive il y a donc en Caml une construction sp ciale let rec destin e introduire les d finitions r cursives Cette construction tablit une liaison de la forme suivante
580. x et ainsi de suite pour les op rations arithm tiques et logiques lire_m moire et crire m moire pour Load et Store L arr t du processeur lorsqu on rencontre l instruction Stop est mod lis par un d clenchement d exception l exception Arr t 264 exception Arr t let cycle_d horloge lire_instruction pico pc in pico pc lt pico pc taille_du_mot match instruction with Op op ration regi op rande reg2 gt let instruction let argi and arg2 Load gt Store gt Add gt Mult gt Sub gt l Div gt And gt Or gt Xor gt Shl gt Shr gt Sit gt Sle gt Seq gt end Jmp op rande lire_registre regi Fichier simul ml Simulation d un processeur valeur_op rande op rande in begin match op ration with crire_registre reg2 crire_m moire argi crire_registre reg2 crire_registre reg2 crire_registre reg2 if arg2 0 lire_m moire argi arg2 arg2 lire_registre reg2 argi arg2 argi arg2 argi arg2 then raise Erreur division par z ro pico pc 1 else crire_registre crire_registre reg2 crire_registre reg2 crire_registre reg2 crire_registre reg2 crire_registre reg2 crire_registre reg2 crire_registre reg2 crire_registre reg2 reg gt crire_registre reg pico pc pico pc lt valeur_op rande op rande Braz reg adresse gt if li
581. xe concr te des propositions 217 12 5 Syntaxe concr te des propositions Nous d finissons maintenant la syntaxe concr te des propositions et les fonctions qui transforment la syntaxe concr te en syntaxe abstraite Reprenant l approche du chapitre 9 nous allons proc der en deux temps analyse lexicale pour obtenir une suite de lex mes partir d une suite de caract res puis analyse syntaxique pour construire un arbre de syntaxe abstraite partir d une suite de lex mes L analyseur lexical L analyseur lexical dont nous avons besoin est tr s proche de celui du chapitre 9 il doit savoir supprimer les blancs reconna tre les identificateurs noms de variables et distinguer les symboles sp ciaux comme les parenth ses Cependant nous ne pouvons pas r utiliser tel quel l analyseur du chapitre 9 D une part nous avons besoin de reconna tre des lex mes form s d une suite de symboles comme par exemple gt ou lt gt D autre part nous voulons introduire la notion de mot cl r serv Rappelons qu un mot cl est une suite de caract res qui a la forme d un identifi cateur mais qui joue un r le sp cial dans le langage par exemple comme op rateur infixe ou pour introduire des constructions du langage Ainsi if then else sont des mots cl s du langage Caml De m me vrai faux et ou non sont des mots cl s de la syntaxe concr te des propositions Un mot cl est dit r serv s il ne peut
582. ype on v rifie donc que cette inconnue n appara t pas dans le type Le syst me Caml fait la m me v rification comme le prouve l exemple suivant let double f f f Entr e interactive gt let double f f f s Cette expression est de type a gt b mais est utilis e avec le type a La fonction test_d occurrence prend donc une variable en argument puis le type qu on veut lui attribuer et op re une descente r cursive dans les arguments de ce type pour v rifier qu aucun ne contient cette variable Fichier types ml let test_d occurrence var ty let rec test t match valeur_de t with Variable var gt if var var then raise Circularit Variable var ty Terme constructeur arguments gt do_vect test arguments in test ty Pour tester l galit entre la variable dont on cherche les occurrences et une autre variable la fonction test_d occurrence ne doit pas utiliser la fonction d galit struc turelle de Caml en effet toutes les variables qui sont encore inconnues ont la m me structure elles pointent toutes vers le constructeur Inconnue et sont donc structurelle ment gales On utilise donc le test d galit physique qui indique que ces arguments sont rang s la m me place en m moire ce qui assure que ces arguments sont un seul et m me objet L op rateur de test d galit physique de deux valeurs Caml est pr d fini et not l in galit
583. ype par unification dans la suite du typage du programme map_id 1 2 3 int list 1 2 3 map_id int list gt int list lt fun gt La modification de notre contr leur de type pour qu il ob isse cette mani re de traiter les valeurs mutables polymorphes est un exercice facile que nous laissons au lecteur 19 En guise de conclusion Tout a une fin mais ce n est pas triste N CONCLUSION DE CE LIVRE nous aimerions r fl chir sur les id es g n rales qui se d gagent de l ensemble des programmes des deuxi me et troisi me parties de notre ouvrage Et pour terminer en beaut nous esquisserons grands traits ce que pourrait tre l impl mentation d un compilateur Caml en passant rapidement en revue les principales difficult s sp cifiques la compilation des langages fonctionnels 19 1 Une m thodologie de programmation En tudiant les exemples pr sent s dans ce livre vous avez pu constater que la d marche tait souvent la m me nous d finissions d abord une structure de donn es la syntaxe abstraite puis un moyen commode de faire produire par Caml des valeurs de ce type la syntaxe concr te avec son analyseur lexico syntaxique Apr s ces deux tapes en guise de pr ambule nous passions aux choses s rieuses savoir le travail sur la syntaxe abstraite et son interpr tation par des programmes d analyse s mantique Cette m thodologie a commenc tr s t t avec le cr

Download Pdf Manuals

image

Related Search

Related Contents

Operating Instructions  Samsung BD-P1000 User's Manual    Mitel 6865i SIP Phone Release 4.1.0 User Guide  Istruzioni Combi - Systec Therm AG  Harbor Freight Tools 66098 User's Manual  Orientia tsutsugamushi の毒力決定因子  clicando aqui  Samsung BT65FQBPST Manuel de l'utilisateur  Volltext  

Copyright © All rights reserved.
Failed to retrieve file