4.6.1 structures de contrôle conditionnelles

Dans la section 4.1.2, pages 171 et suivantes, nous avons déjà analysé en détail l’implémentation des structures conditionnelles, des quatres messages ifTrue:ifFalse:, ifFalse:ifTrue:, ifTrue: et ifFalse: dans les classes Boolean et ses deux sous-classes True et False. Nous n’allons donc pas y revenir, sauf pour un bref rappel de leur comportement:
  1. expressionBooléenne ifTrue: blocVrai ifFalse: blocFaux
    et
    expressionBooléenne ifFalse: blocFaux ifTrue: blocVrai
    retournent la valeur de blocVrai si la valeur du receveur, donc de expressionBooléenne, est vraie, true. Sinon, si la valeur du receveur est fausse, false, les deux expressions retournent la valeur de blocFaux.
  2. expressionBooléenne ifTrue: blocVrai
    retourne nil si l’expressionBooléenne receveur est évalué en donnant la valeur false, sinon, si l’évaluation du receveur donne la valeur true, la valeur retournée est la valeur de blocVrai.
  3. expressionBooléenne ifFalse: blocFaux
    retourne la valeur de blocFaux si l’évaluation du receveur donne la valeur false, sinon la valeur retournée est nil.

Rappelons que blocVrai et blocFaux sont des blocs sans argument et que le receveur, expressionBooléenne, doit toujours s’évaluer soit à true, soit à false. Sinon, comme montré dans la figure 4.29, si nous envoyons un de ces messages à un receveur non booléen, comme dans:

1 ifTrue: [Transcript show: ’impossible’; cr]
SQUEAK affiche une fenêtre d’erreur indiquant que le receveur n’est pas une expression booléenne.70

PIC

FIG. 4.29: Indication d’erreur après l’envoi du message ifTrue: à un receveur non booléen


La partie expressionBooléenne peut naturellement être aussi une composition d’expressions booléennes. Pour composer de telles expressions, SQUEAK nous livre les sélecteurs booléens |, or:, &, and:, not, xor:, ==> et eqv:.

Les sélecteurs | et or: représentent tous les deux l’opération logique ou, la disjonction que nous avons déjà rencontré dans les solutions aux exercices, page 595 et suivantes. Rappellons que l’opération logique

A ou B
retourne vrai si au moins un des arguments A ou B est vrai. La différence entre le message binaire | et le message à mot clef or: réside d’abord dans le fait que or: prend en argument un bloc (sans argument) et | prend en argument une expression booléenne. Ainsi les deux expressions suivantes:
true | false
true or: [false]
retournent true, puisque le receveur, donc au moins un des arguments, est vrai (true). L’autre différence est que le message binare | évalue dans tous les cas son argument, pendant que le message à mot clef or: n’évalue le bloc argument que si nécessaire, c’est-à-dire: que si le receveur est false, puisque seulement dans ce cas la valeur de vérité de l’expression entière dépend de l’argument. Par exemple, l’expression:
true or: [Transcript show: ’la paresse’; cr. true]
retourne true mais n’affiche rien dans le Transcript, puisque la valeur de vérité de cette disjonction est déjà déterminée par le receveur et il n’est donc pas nécessaire d’evaluer le bloc argument. Par contre, l’expression:
false or: [Transcript show: ’la paresse’; cr. true]
retourne également true (puisque la valeur du bloc argument est la valeur de la dernière expression de la séquence d’expressions composant le bloc) mais elle affiche également dans le Transcript la chaîne de caractères “la paresse”, puisque la valeur de vérité de cette disjonction ne peut être déterminée qu’après évaluation du bloc argument.

Si nous évaluons l’expression:

true | [Transcript show: ’la paresse’; cr. true] value
bien que le receveur détermine déjà la valeur de vérité (true), SQUEAK affiche néanmoins dans le Transcript la chaîne de caractères “la paresse”. Nous appelons le message or: un ou paresseux ou une disjonction paresseuse, ou paresseux réfère à l’économie d’évaluation.71

Le message binaire & et le message à mot clef and: représentent l’opérateur logique et, la conjonction. Une conjonction

A et B
n’est vraie que si les deux arguments, A et B sont vraies. Comme pour les opérateurs de disjonction, & évalue toujours son argument, pendant que and: n’évalue l’argument que si nécessaire, c’est-à-dire: que si le receveur est true. Si le receveur est false, on sait que la conjonction entière est false aussi. and: est le et paresseux ou la conjonction paresseuse.

Pour la complétude: l’opérateur not est l’opérateur de négation ou d’inversion, la transmission true not retourne false et la transmission false not retourne true.

Le message ==> représente l’opérateur logique de l’implication. Une implication est fausse, false en SMALLTALK, seulement si le receveur est vrai, true, et l’argument est faux. Pour ce message l’argument doit être un bloc et il est implémenté dans la classe Boolean comme:

==> unBloc  
    self not or: [unBloc value]
C’est donc une implication paresseuse!

Les deux messages de composition d’expressions booléennes restantes, eqv: et xor: prennent en argument une expression booléenne. Ce sont donc des messages non paresseux. Le message eqv: représente l’opérateur d’équivalence logique, ce qui en SMALLTALK correspond à un simple test d’identité entre receveur et argument. Le message xor: représente l’opérateur de la disjonction exclusive, le ou exclusif, le soit l’un, soit l’autre, mais pas les deux à la fois. Il retourne true si le receveur et l’argument sont différents. Ci-dessous l’implémentation dans la classe Boolean des ces deux messages:

eqv: expressionBooleene  
    self == expressionBooleenne  
 
xor: expressionBooleenne  
    (self == expressionBooleenne) not