• Aucun résultat trouvé

7.3.1

D´ecision

I L’expression if expr1 then expr2 else expr3 o`u expr1 est une expression de type bool, et o`u les expres- sions expr2 et expr3 sont forc´ement de mˆeme type, constitue une structure d´ecisionnelle. Lorsque la condition expr1 vaut true, la structure est ´equivalente `a expr2, et dans le cas contraire lorsque expr1 vaut false, la structure est ´equivalente `a expr3.

I D’abord dans le cas o`u expr2 et expr3 sont de type unit :

let x = r e a d _ i n t () in if x >= 0

t h e n p r i n t _ s t r i n g " p o s i t i f "

e l s e p r i n t _ s t r i n g " n ´e g a t i f "

Ici, la condition est x >= 0. Les expressions print string "positif" et print string "n´egatif" sont toutes les deux de type unit.

I Lorsque les expressions expr2 ou expr3 sont construites comme juxtapositions de plusieurs expressions, il faut d´elimiter le bloc. Cela se fait de pr´ef´erence avec begin et end, bien qu’on puisse aussi utiliser des parenth`eses en th´eorie.

Voici l’exemple pr´ec´edent dans lequel on a rajout´e l’affichage de la valeur absolue du nombre lorsque celui-ci est n´egatif : let x = r e a d _ i n t () in if x >= 0 t h e n p r i n t _ s t r i n g " p o s i t i f " e l s e b e g i n p r i n t _ s t r i n g " n´egatif , de v a l e u r a b s o l u e : "; p r i n t _ i n t ( abs x ) end

I Maintenant dans le cas o`u expr2 et expr3 ne sont pas de type unit : ces deux expressions doivent ˆetre de mˆeme type, et ce type est alors celui de l’ensemble de la structure if.

Par exemple, lorsque x est d´efini, l’expression :

if x >= 0 t h e n " p o s i t i f " e l s e " n ´e g a t i f "

est de type string, puisque "positif" et "n´egatif" sont tous les deux de type string. Ainsi :

let x = r e a d _ i n t () in

p r i n t _ s t r i n g (if x >= 0 t h e n " p o s i t i f " e l s e " n ´e g a t i f ") ;

affiche le signe de l’entier x donn´e par l’utilisateur.

On peut aussi associ´e un nom `a l’expression form´ee par la structure if :

let x = r e a d _ i n t () in

let s i g n e = if x >= 0 t h e n " p o s i t i f " e l s e " n ´e g a t i f " in

p r i n t _ s t r i n g s i g n e

Dans ce cas, il sera pr´ef´erable de pr´esenter cela sur plusieurs lignes, comme on pr´esente les fonctions :

let x = r e a d _ i n t () in let s i g n e = if x >= 0 t h e n " p o s i t i f " e l s e " n ´e g a t i f " in p r i n t _ s t r i n g s i g n e

I Voyons un cas o`u expr2 et expr3 o`u sont des juxtapositions d’expressions, d’un autre type que unit. En fait on l’a d´ej`a utilis´e, pour le jeu “C’est plus, c’est moins” en r´ecursif :

if c i b l e > e s s a i t h e n b e g i n p r i n t _ s t r i n g " C ’ est p l u s \ n "; s u c c ( c i b l e jeu ) end e l s e if c i b l e < e s s a i t h e n b e g i n p r i n t _ s t r i n g " C ’ est m o i n s \ n ";

s u c c ( c i b l e jeu ) end e l s e b e g i n p r i n t _ s t r i n g " C ’ est g a g n ´e !\ n "; 1 end ;

I Terminons avec le bloc du else implicite.

L’expression if expr1 then expr2 est ´equivalente `a if expr1 then expr2 else (). Par cons´equent, expr1 doit ˆetre de type bool et expr2 doit ˆetre de type unit.

Par exemple : let x = r e a d _ i n t () in if x > 0 t h e n p r i n t _ s t r i n g " p o s i t i f " est ´equivalent `a let x = r e a d _ i n t () in if x > 0 t h e n p r i n t _ s t r i n g " p o s i t i f " e l s e ()

Si expr2 n’est pas de type unit, cela provoque une erreur de type. Illustration :

let x = r e a d _ i n t () in

p r i n t _ s t r i n g (if x > 0 t h e n " p o s i t i f ") F i l e " t e s t . ml " , l i n e 2 , c h a r a c t e r s 28 -37:

T h i s e x p r e s s i o n has t y p e s t r i n g but is h e r e u s e d w i t h t y p e u n i t

Erreur sur la chaˆıne "positif" qui n’est pas de type unit.

7.3.2

Calcul bool´een

I Le ET du calcul bool´een, op´erateur &&, est en fait ´equivalent `a une structure avec des if. Cherchons l’´equivalent de expr1 && expr2. Si expr1 est vrai, alors si expr2 est aussi vrai, le r´esultat est vrai. Mais si expr1 ou expr2 est faux, le r´esultat est faux. Ceci s’´ecrit :

if e x p r 1 t h e n b e g i n if e x p r 2 t h e n t r u e e l s e f a l s e end e l s e f a l s e

Mais l’expression if expr2 then true else false est ´equivalente `a la valeur de expr2 directement. Donc en simplifiant le code et la pr´esentation, il reste :

if e x p r 1

t h e n e x p r 2

e l s e f a l s e

Conclusion :

L’expression expr1 && expr2 o`u les deux expr1 et expr2 sont de type bool est ´equivalente `a if expr1 then expr2 else false.

I Il y a une observation importante `a faire : si expr1 est ´evalu´e `a faux, alors expr2 ne sera mˆeme pas ´evalu´e, puisqu’on est d´ej`a sˆur que le r´esultat de expr1 && expr2 est faux.

Pour v´erifier cela, on va utiliser des expressions qui affichent quelque chose lorsqu’elles sont ´evalu´ees. Pour com- mencer, on va ainsi prendre pour expr1 l’expression print string "expr1 "; true et pour expr2 l’expression print string "expr2 "; true, et voir ce qu’il se passe en affichant le r´esultat de expr1 && expr2 :

let b = ( p r i n t _ s t r i n g " e x p r 1 "; t r u e) && ( p r i n t _ s t r i n g " e x p r 2 "; t r u e) in

p r i n t _ s t r i n g ( s t r i n g _ o f _ b o o l b ) ;

Ce code affiche expr1 expr2 vrai. On en d´eduit que expr1 a ´et´e ´evalu´e, puis expr2, et que expr1 && expr2 ´etait vrai.

Regardons maintenant ce qu’il se passe si on fait que expr2 soit faux :

let b = ( p r i n t _ s t r i n g " e x p r 1 "; f a l s e) && ( p r i n t _ s t r i n g " e x p r 2 "; t r u e) in

p r i n t _ s t r i n g ( s t r i n g _ o f _ b o o l b ) ;

Ce code affiche cette fois expr1 faux. On en d´eduit que expr1 a ´et´e ´evalu´e, mais pas expr2, et que le r´esultat de expr1 && expr2 ´etait faux.

I On va calquer le raisonnement effectu´e pour le ET pour traiter le OU. L’expression expr1 || expr2 vaut vrai lorsque l’une ou l’autre des deux expressions est vraie. Traduisons cela avec des if. Si expr1 est vrai, on est sˆur que le r´esultat est vrai. Sinon il faut regarder si expr2 est vrai ou faux.

On a donc : if e x p r 1 t h e n t r u e e l s e b e g i n if e x p r 2 t h e n t r u e e l s e f a l s e end

qui se simplifie tout de suite en :

if e x p r 1

t h e n t r u e e l s e e x p r 2

Conclusion :

L’expression expr1 || expr2 o`u les deux expr1 et expr2 sont de type bool est ´equivalente `a if expr1 then true else expr2.

Vous pouvez v´erifier que lorsque la condition expr1 est vrai, la condition expr2 n’est mˆeme pas ´evalu´ee.

7.3.3

Boucles

I La structure : for c o m p t e u r = e x p r 1 to e x p r 2 do e x p r 3 d o n e o`u

• compteur est le nom du compteur,

• expr1 et expr2 sont des entiers, valeurs initiale et finale.

• expr3 est une expression de type unit o`u l’on peut utiliser le nom du compteur, le corps de la boucle,

forme une expression de type unit, qui se comporte comme la r´ep´etition de expr3 pour toutes les valeurs de compteur comprises entre expr1 et expr2 inclus. S’il n’existe pas de telle valeur pour le compteur, alors la boucle ne fait rien et est ´equivalente `a ().

Remarque : les valeurs initiales et finales du compteur, expr1 et expr2, ne sont ´evalu´ees qu’une seule fois au d´ebut. La preuve :

for i = ( p r i n t _ s t r i n g " e x p r 1 "; 1) to ( p r i n t _ s t r i n g " e x p r 2 "; 5) do

p r i n t _ i n t i ;

d o n e;

affiche expr1 expr2 12345.

I La structure :

w h i l e e x p r 1 do

e x p r 2

d o n e

o`u expr1 (la condition de la boucle) est de type bool et expr2 (le corps de la boucle) de type unit est une expression de type unit, qui se comporte comme la r´ep´etition de expr2 tant que l’expression expr1 est ´evalu´ee ` a vrai. Par exemple : let i = ref 1 in w h i l e ( p r i n t _ s t r i n g " e x p r 1 "; ! i <= 5) do p r i n t _ i n t ! i ; i n c r i ; d o n e;

affiche "expr1 1 expr1 2 expr1 3 expr1 4 expr1 5 expr1". Ainsi l’expression expr1 qui d´etermine l’ex´ecution de la boucle est ex´ecut´e tout au d´ebut, mais aussi tout `a la fin : la fois o`u elle est ´evalu´ee `a faux.

7.3.4

Fonctions

I La d´efinition d’une fonction :

let a r g _ d e _ l a _ f o n c t i o n a r g _ 1 a r g _ 2 ... a r g _ N = e x p r 1 in

o`u arg de la fonction et tous les arg i sont des noms, forme une expression de type : t y p e ( a r g _ 1 ) - > t y p e ( a r g _ 2 ) - > ... - > t y p e ( a r g _ N ) - > t y p e ( e x p r _ 1 )

les types des arguments ´etant d´eduits de l’utilisation qui en est faˆıte dans expr1.

I L’expression :

n o m _ d e _ f o n c t i o n e x p r _ 1 e x p r _ 2 ... e x p r _ N

lorsque nom de fonction est associ´e `a une fonction de type

t y p e _ a r g _ 1 - > t y p e _ a r g _ 2 - > ... - > t y p e _ a r g _ N - > t y p e _ r e t o u r

est une expression de type type retour, `a condition que chaque expr i soit de type type arg i.

Documents relatifs