Bonjour. Alors aujourd'hui on va revenir sur quelque
chose que vous avez déjà vu dans les séquences
précédentes, mais on va vraiment réefoncer le clou dans cette séquence.
Donc les caractères, les chaines de caractères et les symboles.
Ce que vous allez apprendre, c'est vraiment comment on
manipule les caractères, comment sont représentés les
chaines de caractères et qu'est-ce que c'est un symbole
par rapport à une chaîne de caractères.
Donc on revient à la base, les caractères.
Donc les caractères en Pharo sont représentés, vous vous
souvenez, on commence par un dollar suivi d'une lettre.
Donc ça, c'est pour représenter les caractères sous forme littérale.
D'accord. Et puis les caractères qu'on ne peut pas
représenter, qui n'ont pas de formes représentables
typiquement l'espace, le tab, le cr return, donc ça c'est
le caractère qui permet de passer à la ligne.
Donc en fait, on utilise la classe caractère auquel on va
envoyer un message pour obtenir ce caractère-là.
Donc les chaînes de caractères maintenant.
Les chaînes de caractères en Pharo sont représentées donc
entre simples côtes. Donc ici, c'est ce caractère-là.
Donc ici, on a eu une chaîne de caractères éclair au
chocolat qui commence ici et qui se termine ici.
On peut lui envoyer un message Size, ça nous rend
18. Donc cette chaîne de caractères contient bien 18 caractères.
On peut manipuler cette chaîne de caractères.
Par exemple, je peux dire caractère space split cette
chaîne de caractères-là. Donc ça veut dire que je vais
découper cette chaîne en fonction des espaces.
Et ça va me rendre une collection ordonnée de 3 éléments.
Donc la chaîne a bien été coupée en 3 éléments.
Alors, en fait les chaînes de caractères sont des
collections comme les autres en Pharo.
Donc c'est vraiment une collection instance de la classe string.
Mais la classe string va hériter des classes de collection.
Donc je peux utiliser toutes les méthodes classiques.
Vous vous souvenez sur les collections on a une API
commune qui existe pour toutes les collections, donc par
exemple, at pour toutes les collections indexées.
Donc si je fais éclair au chocolat at 1, donc je veux l'élément
1 de cette collection, ça me retourne bien le caractère E.
D'accord qui était bien ce E là.
Ensuite je peux utiliser do qui permet de parcourir l'ensemble
des éléments d'une collection.
Et donc à chaque tour de boucle, le paramètre du bloc ici
vaudra le premier élément de la collection, le deuxième
et caetera, jusqu'au bout.
Donc petite subtilité, vu que les chaines de caractères
sont définies par des simple côtes.
Donc si je veux mettre des côtes dans une chaîne de
caractères l'astuce c'est de les doubler.
Si j'en mets 2 côte-à-côte, ça veut dire que je veux
insérer une côte dans ma chaîne de caractère.
D'accord. Par contre attention, la subtilité c'est qu'elle
ne compte que pour un seul élément dans la chaîne de caractères.
Donc ici vous avez l'exemple, si je fais l'éclair au
chocolat at 2, d'accord. Donc, je veux l'élément 2 de
cette collection, ça me retourne bien le caractère côte.
Et si je demande at 3, ça me retourne le E qui est ici.
D'accord. Donc même si on affiche 2 côtes, ça prend
l'espace que pour une seule côte.
Donc les chaînes de caractères sont des collections comme les autres.
Donc je peux les manipuler comme des collections, je peux
dire que je veux par exemple le dernier élément d'une
chaîne de caractères, donc je fais str at str size, donc
je récupère le dernier élément.
Je vous rappelle en Pharo, les collections commencent à l'indice
1, donc le dernier élément c'est la taille de la chaîne.
Ou on peut utiliser la méthode plus simple qui est last
pour récupérer directement le dernier élément de la collection.
Donc pour créer des chaînes, on a plusieurs techniques
pour créer des chaînes, on a la technique simple, c'est
je prends un symbole et j'utilise une méthode de conversion.
Donc je convertis ce symbole en chaîne de caractères avec
asString, ou je peux envoyer printString à n'importe quel
objet qui va permettre de récupérer une représentation
sous-forme de chaîne de caractères de l'objet.
Et puis, je peux créer une méthode de création
directement d'une collection, vous vous souvenez on peut
with à n'importe quelle classe de collection pour créer
une nouvelle collection, contenant directement un certain
objet à l'intérieur. Donc, si je fais string with le
caractère A, ça va me retourner une chaîne de caractères
qui ne contient qu'un seul caractère A.
Pour concaténer des chaînes de caractères, on l'avait
déjà vu, c'est le message virgule.
Donc, je peux envoyer le message virgule à une chaîne de
caractères et je passe en paramètre une autre chaîne de
caractères, ça va m'en construire une nouvelle qui est la
concaténation des 2, bien sûr je peux chaîner.
Attention toutefois si je fais ça, donc si je reprends le
même exemple, il faut bien comprendre qu'ici j'ai créé
des chaînes intermédiaires inutiles.
Donc en fait, j'ai ce premier message qui a été envoyé à
cette chaîne-là, avec ce paramètre-là, donc on a une
première chaîne ici concaténée qui a été créée, d'accord pour tout ça.
Cette chaîne concaténée on lui a envoyé le message
virgule avec ce paramètre-là et une autre chaîne a été
créée, qui est le résultat final.
Donc, on a une chaîne intermédiaire qu'on n'a pas vue,
qui a été créée et qui fait perdre du temps en fait dans le temps de calcul.
D'accord. Donc vous pouvez utiliser, vous avez eu la
séquence sur le benchmarking, vous pouvez utiliser le
benchmarking pour voir exactement ce qu'il en est, et s'il
ne serait pas plus avantageux d'utiliser un string, d'accord.
Donc ici, je créé une chaîne de caractères, d'accord et
je dis que je vais lui définir un contenu à l'aide d'un stream, d'accord.
Et je peux directement envoyer des chaînes de caractères
dans ce string pour créer la chaîne finale.
Donc, là j'évite le fait de créer des chaînes intermédiaires.
Donc maintenant les symboles.
Donc les symboles en fait syntaxiquement, vous vous
souvenez, ils commencent par un dièse.
Et puis ensuite il y a une chaîne de caractères.
Donc ça c'est un symbole littéral.
C'est une sorte de chaîne de caractères mais attention,
elles sont uniques dans le système.
C'est-à-dire que n'importe où dans mon programme si j'écris
#blabla, et n'importe où dans le programme je réécris
#blabla, c'est le même objet que je désigne d'accord, c'est
la même instance. Donc, elles sont vraiment uniques dans le système.
Donc ici, j'ai l'exemple avec Calvin, je fais #calvin ==
#calvin, donc ça me renvoie vrai, c'est bien le même objet.
D'accord, ce n'est pas le cas pour les chaînes de caractères, ça dépend.
Cela va dépendre des optimisations appliquées par le compilateur.
Donc les symboles par rapport aux chaînes de caractères,
la différence c'est vraiment ça.
Un symbole c'est quelque chose qui va être uniquement en
lecture, on ne peut pas modifier un symbole.
On va créer un nouveau symbole.
C'est un objet qui est unique, donc si je le référence
plusieurs fois dans mon programme, je référence le même objet.
Les chaînes de caractères elles sont mutales.
Je peux modifier le contenu d'une chaîne de caractères.
Il y a marqué "pour l'instant", puisque c'est en
pourparlers de le changer ça dans Pharo dans dans le futur.
Les symboles sont souvent utilisés pour désigner les
sélecteurs de méthode.
D'accord. Et les symboles sont extrêmement utilisés en
tant que clé dans les dictionnaires et notamment les IdentityDictionnary.
Vous vous souvenez qu'on va comparer les éléments
et on va être capable de calculer facilement des hash à
partir d'un symbole pour la clé dans un dictionnaire.
Donc ce que vous devez retenir de cette séquence, ce qui
est vraiment important c'est que les chaînes des
caractères sont des collections comme les autres, et que
les symboles sont des chaînes de caractères uniques et en lecture seule.
Donc imutables, on ne peut pas les modifier.