Dans cette séquence, nous allons voir les booléens et les conditions en Pharo.
Il existe deux objets booléens, true et false sauf que true, est l'unique instance de la classe True et false, c'est l'unique instance de la classe False. Et on va envoyer des messages à ces objets pour mettre en place ces opérations booléennes, mouvoir des structures alternatives telles que ifFalse, ifTrue, etc.
Dans le premier exemple:
false & ( 1 error:'crazy' ) ">>> Error: crazy"
On envoie le message “&”, donc qui est un opérateur binaire à l'objet false et puis on lui passe un paramètre, donc le paramètre est une expression ici entre parenthèses, c'est “( 1 error:'crazy')”. Cette expression va déclencher une erreur et on voit que l'évaluation totale de toute cette expression déclenche bien une erreur.
Pourquoi? Parce que l'opérande à droite a été aussi évalué dans cette expression booléenne. Il a même été évalué en premier car les parenthèses ont la priorité, ce qui produit l'erreur.
Si on voulait en fait la version paresseuse des opérateurs booléens, il faut utiliser la méthode “and:” de la classe booléen comme dans l'exmple ci-dessous:
false and: [ 1 error:'crazy' ].
Cette méthode “and:” prend en paramètre un bloc. On appelle que les blocs contiennent des expressions, mais la définition d'un block ne déclenche pas l'exécution des expressions qu'il contient, donc pour l'instant, les expressions qu'il contient ne sont pas évaluées. Elles le seront seulement si le premier opérande est vrai.
Dans ce deuxième exemple, l'expression retourne false sans avoir évalué le contenu du block passé en paramètre, donc un opérateur paresseux classique, mais construit cette fois avec des blocs.
En Pharo, les conditionnels, donc les if, les false, les why, etc. sont toujours des messages envoyés à des booléens ou à des blocs.
Prenons un autre exemple:
Weather isRaining ifTrue: [ self takeMyUmbrella ] ifFalse: [ self takeMySunGlasses ]
Le message “ifTrue:if:False” qui est la structure alternative classique dans tous les langages de programmation, sauf qu'en Pharo, c'est aussi un message et je peux envoyer le message “ifTrue:ifFalse” à un objet booléen donc “Weather isRaining” est une expression qui va retourner un booléen. On passe en paramètre de ce message ifTrue:ifFalse deux blocs:
Ce message “ifTrue:ifFalse:”, il est extrêmement utilisé au cœur de Pharo, il est au cœur du système, il est tellement important qu'il a été optimisé de façon assez avancée pour pouvoir être efficace et ne pas ralentir tout le système bien évidemment.
si on revient sur l'implantation des booléens en Pharo, en fait elle est extrêmement élégante, comme je le disais, les deux objets true et false sont tous deux respectivement instance de la classe True et de la classe False qui elles-même héritent de la classe Boolean.
Ensuite chacune de ces classes va définir un ensemble de méthodes de façon à avoir le comportement attendu. Donc, vous aurez plus d'informations sur cette implantation des booléens qui est élégante dans une prochaine séquence.
Revenons sur le message ifTrue:ifFalse:, donc il existe différentes versions de ces messages, donc on a la version où on a juste le message ifTrue: avec un block en paramètre quand on veut faire juste la première part de l'alternative ou le message complet ifTrue:ifFalse: qui compte bien deux blocs qui permet de faire l'alternative avec le cas où le booléen est vrai ou faux.
C'est bien deux messages différents, là on a le pendant pour ifFalse; sur les classes booléen, les classes True et les classes False.
On a d'autres types de messages pour exprimer les alternatives, ou les conditions. on a par exemple le message “ifEmpty:ifNotEmpty:” que je peux envoyer à une collection.
“ifEmpty:” avec en paramètre le bloc qui sera évalué seulement si la collection receveur est vide. Et puis ifNotEmpty:, c'est la condition inverse donc exécution du bloc lorsque la collection n'est pas vide. Sauf que dans ce cas, on a une subtilité supplémentaire: ce bloc prend un argument.
|aCol| aCol := #( 0 1 2 3 4 5 6 7 8 9 10 ). aCol ifNotEmpty: [ :c | Transcript show: c ].
L'argument en paramètre, c'est la collection elle-même qui n'était pas vide puisque la collection, on a peut-être le résultat d'un calcul complexe et donc on ne va pas redemander la collection dans le bloc, donc la collection, si elle n'était pas vide, elle est passée en paramètres du bloc et elle peut être utilisée dans les expressions du bloc.
En résumé, dans cette séquence, on a vu que les booléens sont des objets comme les autres en Pharo, sont instances des classes True et False qui héritent de booléens, et puis qu'on peut leur envoyer des messages et que ces messages en fait définissent toutes les constructions d'alternatives ou de conditions possibles dans Pharo alors que dans d'autres langages, ce seraient plutôt des structures câblées dans le compilateur.