Retrouvez cet article dans : Linux Pratique 32
Dans ce troisième article1, nous allons découvrir la syntaxe du langage d'implémentation de Squeak : Smalltalk. Nous verrons que la syntaxe est simple et uniforme. Une fois, la syntaxe du langage maîtrisée, il restera à appréhender les structures de contrôle de base de Squeak.
- 1 Voir : LP #28 ;Â
-  Squeak, un smalltalk libre multimédia " LP #31 ;
- " Squeak, mon premier programme "
Smalltalk : une syntaxe qui tient sur une carte postale !
La syntaxe d'un langage de programmation n'est généralement pas ce qui est le plus intéressant lorsque l'on aborde un nouveau langage. Heureusement, la syntaxe de Smalltalk est simple. On dit généralement qu'elle tient sur une carte postale ! Le bénéfice est immédiat : elle est rapide à apprendre et on se concentre sur l'essentiel, c'est-à -dire écrire du code qui marche !
La syntaxe de Smalltalk comprend principalement :
- 6 mots réservés :
nil,true,false,self,superetthisContextÂ; - les commentaires ;
- 3 types d'envois de messages (unaires, binaires et à mots clefs) ;
- des littéraux pour représenter les objets de base créés à la compilation ;
- des clôtures lexicales.
Les mots réservés
Les mots réservés sont également appelés des pseudos-variables parce qu'ils sont en lecture seule. Leur valeur est définie par le système et dépend du contexte d'exécution du programme. L'utilisateur ne peut donc pas les modifier :
- self et super font référence au receveur d'un message (on reviendra dessus plus tard).
- nil représente une valeur nulle. C'est la valeur par défaut des variables si elles n'ont pas été initialisées. Attention nil est un objet, unique instance de la classe UndefinedObject (ce qui permet de faire le fameux jeu de mot : nothing is an object), true et false représentent respectivement les valeurs de vérité " vrai " et " faux ". true est l'unique instance de la classe True, false l'unique instance de la classe False, thisContext représente la pile d'exécution. Très utile notamment pour le débogueur de Smalltalk pour accéder au contexte d'exécution.
Les commentaires
Les commentaires sont formés de n'importe quelle séquence de caractères délimitée par des guillemets. Il est possible d'introduire des guillemets dans des commentaires en les entourant de guillemets. Les développeurs Smalltalk font un usage modéré des commentaires, car généralement ils utilisent des noms d'objets ou de méthodes très explicites.
Exemples de commentaires :
"ceci est un commentaire" "ceci est un commentaire sur plusieurs lignes" "ceci est un commentaire avec """un commentaire""" dans un commentaire"
On se reportera à l'article précédent (cf. Linux Pratique #31) pour savoir comment exécuter les expressions Smalltalk données dans cet article.
Identificateurs
Un identificateur Smalltalk est une suite de caractères commençant par une lettre. Un identificateur permet de nommer un objet ou une méthode Smalltalk. Attention à la casse : dateDuJour est différent de DateDuJour.
La convention en Smalltalk est d'identifier clairement les noms que l'on donne aux objets et aux méthodes
en concaténant les mots les uns aux autres :
ceciEstUnIndentificateur, montantFacture... Cela ne devrait pas poser de problèmes à ceux qui sont des adeptes des wikis (le concepteur du premier wiki, Ward Cunnigham est d'ailleurs un smalltalkien de renom).
Les identificateurs qui représentent des variables globales, c'est-à -dire connus dans tout le système, commencent forcément par une majuscule. Par exemple : Transcript. Les noms de classes sont des variables globales : OrderedCollection, Integer...
On remarquera que les variables ne sont pas typées en Smalltalk. L'opérateur d'affectation (:=) permet l'association d'un objet à un identificateur.
  x := 2. => affecte à x l'objet 2 ;
 y := 'Hello World'. => affecte à y l'objet 'Hello World' ;
aujourdhui := Date today. => affecte à aujourdhui le résultat de l'expression, c'est-à -dire un objet de la classe Date.
Il existe plusieurs catégories de variables suivant l'endroit et la façon dont on les utilise.
Lorsque l'on veut introduire de nouvelles variables locales à un contexte, on les énumère en les entourant de barres verticales : | |.
Par exemple, il est possible d'effectuer directement ce code dans un Espace de Travail (Workspace). On déclare la variable d, on affecte le résultat de l'expression 3+4, c'est-à -dire 7, à cette variable. Ensuite, on multiplie par deux la valeur contenue par la variable et on obtient 14.

Littéraux
Les littéraux sont les expressions qui représentent des objets couramment employés comme les nombres, les chaînes, les booléens, les tableaux... Ces objets ne sont pas créés en envoyant le message new à une classe comme pour les non-littéraux, mais utilisent une syntaxe particulière.
Les nombres
12=> nombre entier ;3+4=> somme de deux entiers ;3.141516=> nombre de la classe Float.
Précision : les entiers sont en précision aussi importante que l'on souhaite.
Les caractères
Ce sont des instances de la classe Character, ils sont précédés du caractère $ :
$a, $Z, $& sont des caractères. Les caractères n'ayant pas de représentation graphique comme [espace] sont obtenus en envoyant un message à la classe correspondante : Character space.
Chaînes de caractères
Les chaînes de caractères sont formées d'un ensemble de caractères encadrés par des quotes :
'Ceci est une chaîne de caractères'. La chaîne vide est bien sûr : ''.
Les chaînes de caractères sont des objets de la classe String, sous-classe de la classe Array.
Symboles
Un # suivi d'une suite quelconque de caractères forme un symbole (objet de la classe Symbol, sous-classe de String). La spécificité d'un symbole est d'être unique dans tout le système.
#SymboleUnique == #SymboleUnique retourne donc toujours vrai. == est la méthode qui compare si deux références pointent sur le même objet contrairement à = qui dit si deux objets sont égaux. Donc ici #SymboleUnique fait référence au même objet en mémoire.
Les tableaux
Un tableau est une instance de la classe Array. Il s'agit d'une collection d'objets de taille fixe auxquels on peut accéder par un indice numérique. Pour créer un tableau, deux possibilités existent :
#()définit un tableau créé à la compilation. Les objets sont séparés par des espaces :#(1 2 true 1.0 #(1 2 3)). On remarquera que les objets dans le tableau sont de nature hétérogène. En effet, le typage est dynamique en Smalltalk.{}définit un tableau créé à l'exécution. Les objets sont séparés par des points : { 1. 3+4. true not.Date today} crée le tableau : #(1 7 false 21 April 2005). Cette forme permet de construire un tableau initialisé dynamiquement à l'exécution avec des expressions Smalltalk, alors que dans la première forme, il n'est possible de mettre dans le tableau que des valeurs littérales.
L'accès aux valeurs d'un tableau s'effectue au moyen des méthodes at: et at:put:. L'envoi de message at: permet de récupérer la valeur du tableau qui se trouve à l'indice passé en paramètre, at:put: permet de modifier la valeur se trouvant à l'indice indiqué par un nouvel objet. Notez que le premier élément d'un tableau en Smalltalk se trouve à l'indice 1 et non zéro.
t := #(3 1 4 1 5 9). t at:1. t at: 1 put: 4.
L'évaluation de t retourne : #(4 1 4 1 5 9)
L'envoi de messages : un langage naturel !
L'envoi de message est l'opération de base de Smalltalk. Tous les calculs s'effectuent par envoi de messages à des objets. Une expression d'envoi de message Smalltalk est de la forme : <receveur> <message>. La résolution d'un message invoque alors la méthode de même nom, méthode qui est définie dans la classe du receveur du message ou une classe ancêtre.
On peut considérer que Smalltalk est une version simplifiée du langage naturel où les objets seraient les noms, les verbes les messages, les compléments les paramètres. Chaque expression Smalltalk est séparée de la suivante par un point (.), de la même façon qu'une phrase en langage naturel est séparée de la suivante par un point. Le point est un séparateur d'expressions et non pas un terminateur : il n'est pas nécessaire de le mettre à la fin d'une méthode ou d'un bloc.
Voici des exemples d'envois de messages (ne pas tenter de les exécuter car les objets correspondants n'existent pas) :
album play. album playTrack: 1. album repeatTracksFrom: 1 to: 10.
En français, cela donne :
album joue. album jouePiste: 1. album repèteLesPistesDe: 1 a: 10.
Le sens se déduit assez aisément de la syntaxe des expressions Smalltalk.
Il existe 3 formes d'envois de messages :
Messages unaires
Un objet est suivi du verbe (méthode), il n'y a pas d'argument. Par exemple :
- album play.
=> la méthode play est déclenchée sur l'objet album. - 0.7 sin.
=> on envoie le message sin à l'objet 0.7. - true not.
=> on envoie le message not à l'objet true. - 'squeak' reversed.
=> retourne la chaîne inversée.
Messages binaires
Un message binaire, principalement utilisé pour les opérations arithmétiques, est formé d'une méthode infixée avec des objets. Le nom d'une méthode binaire est formée par un symbole ou deux symboles dans la liste : + - / \ * ~ < > = @ & ?
Voici quelques exemples de messages binaires :
3 + 4. => on envoie le message :+ 4à l'objet3, le résultat est7. Une banale opération arithmétique est également vue comme un envoi de messages en Smalltalk !'Hel','lo'. => on envoie le message :,'lo'à la chaîne de caractère'Hel', le résultat est l'objet'Hello'.10@10. => le message@10est envoyé à l'entier 10 et a pour conséquence de construire une instance de la classePoint,qui représente un point du plan cartésien.
Messages à mots-clés
Lorsqu'il y a un ou plusieurs arguments, Smalltalk utilise une syntaxe assez originale, qui peut surprendre dans un premier temps l'utilisateur habitué à celle de C ou Java, mais qui s'avère finalement très simple à lire. Ce sont les messages à mots-clés où les arguments sont insérés entre les éléments du nom de la méthode. Par exemple :
Color r:10 g:10 b:20 alpha: 0.6. => envoi d'un message à trois arguments (les trois composantes de couleur rouge, vert, bleu) avec une valeur d'alpha-blending à la classe Color pour construire l'instance correspondante. L'équivalent en syntaxe Java est Color.rgbalpha(10,10,20, 0.6).2 raisedTo: 10. => envoi du message raisedTo: (c'est-à -dire " mettre à la puissance ") en utilisant 10 comme paramètre.
L'idée, c'est d'avoir une expression Smalltalk qui peut quasiment se lire comme une phrase de français (ou d'anglais) et communique l'intention du développeur à celui qui lit le code. Un message à mots-clés est un message dont le nom de méthode contient au moins un :. Un : précède donc un argument.
Il est bien sûr possible de combiner ces trois formes de base d'envois de messages, si on connaît les règles de priorités d'évaluation suivantes : les envois de messages unaires sont prioritaires sur les binaires qui sont eux-mêmes prioritaires sur les envois à mots-clés. Entre opérateurs de même priorité, on procède par évaluation de gauche à droite. Les parenthèses permettent de modifier naturellement l'évaluation par défaut.
3 squared reciprocal negated. => Applique successivement les méthodes unaires :squared,reciprocaletnegated.Speaker woman say:'Hello, readers of LinuxPratique.'. => On envoie le message unairewomanà la classeSpeakerqui retourne une instance de cette classe initialisée avec une voix féminine, puis on envoie à cette instance un message à mots clés qui déclenche la lecture du texte.
Attention aux erreurs potentielles, l'évaluation de l'expression Smalltalk : 2 + 3 * 4 / 2 donne 10 et pas 8 comme on pourrait s'y attendre dans un premier temps... En effet, pour Smalltalk, le + ou * sont des envois de messages comme les autres et on utilise ici la priorité consistant à effectuer les opérations de gauche à droite au lieu d'utiliser les priorités habituelles des mathématiques. Une fois l'habitude prise, le principal avantage est qu'il est alors possible d'introduire ses propres opérateurs sans avoir à gérer de difficiles problèmes de priorités. Ceci permet d'avoir également une grammaire très simple et uniforme pour Smalltalk.
De la même façon que les opérateurs arithmétiques, les opérateurs de comparaisons (=, <, >...) ne sont pas des opérateurs prédéfinis en Smalltalk. Ce sont en fait des envois de messages comme les autres.
Smalltalk offre une facilité supplémentaire pour exécuter une suite d'envois de messages sur le même objet : la cascade de messages. Par exemple, comparer sur l'exemple suivant qui ouvre à l'écran une montre à fond jaune, la version sans et avec cascade :
Le point-virgule (;) permet de cascader plusieurs envois de messages au même objet, ici une instance de la classe WatchMorph.

En conclusion
Dans cet article, nous avons abordé la syntaxe de Smalltalk. Il vous est maintenant possible de comprendre tout le code de Squeak. Il ne sera plus nécessaire d'y revenir, puisque tous les aspects syntaxiques ont été abordés dans ces quelques pages. Cette syntaxe légère et uniforme est un des aspects les plus puissants de Smalltalk, elle permet au développeur de se concentrer sur les aspects essentiels de conception de son application. Pour un débutant en programmation objet, c'est du temps de gagné. Il ne passe pas plusieurs semaines voire mois à comprendre les subtilités de la syntaxe comme avec d'autres langages.
Dans notre prochain article, nous présenterons les structures de contrôle de Squeak (conditionnelle, itération...). Nous verrons alors qu'elles utilisent également la syntaxe uniforme de Squeak et qu'il est même possible d'introduire ses propres structures de contrôle.
D'ici là , vous pouvez parcourir l'ensemble des classes du système de Squeak qui vous sont offertes. N'essayez pas de tout comprendre, mais il vous est déjà possible d'appréhender certaines choses et éventuellement de les modifier.
Liens
- Le site officiel de Squeak a été remis à jour récemment : http://www.squeak.org/
- Un site web francophone est cours de réalisation : http://www.squeakfr.org/
- Le wiki de la communauté française propose des tutoriels et des aides pour installer et utiliser Squeak : http://community.ofset.org/wiki/Squeak
- Le groupe des utilisateurs européens de Smalltalk (European Smalltalk User Group). L'adhésion est gratuite : http://www.esug.org/
Retrouvez cet article dans : Linux Pratique 32

