LES LANGAGES DE PROGRAMMATION
Transcription
LES LANGAGES DE PROGRAMMATION
LES LANGAGES DE PROGRAMMATION 27 CHAPITRE 2 LES LANGAGES DE PROGRAMMATION OBJECTIFS ■ DÉFINIR ET PRÉCISER LE RÔLE DES LANGAGES DE PROGRAMMATION DANS L’EXPLOITATION DES ORDINATEURS. ■ CARACTÉRISER CES LANGAGES EN METTANT EN ÉVIDENCE LEURS PROPRIÉTÉS LEXICALE, SYNTAXIQUE ET SÉMANTIQUE. ■ CLASSIFIER LES LANGAGES DE PROGRAMMATION EN TENANT COMPTE DE LEUR PROXIMITÉ DU LANGAGE NATUREL ET DU TYPE DE PROGRAMMATION QU’ILS PERMETTENT DE RÉALISER. 28 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI LES LANGAGES DE PROGRAMMATION Dans le chapitre précédent, nous avons traité en profondeur de la notion de programme et mis en évidence l’importance de l’algorithme dans le processus de résolution de problème. Toutefois, si l’on veut résoudre un problème donné à l’aide de l’ordinateur, cela nécessite, en plus de l’algorithme, un langage de programmation permettant d’automatiser les opérations. Ce chapitre est consacré à l’étude de ces langages. Après avoir défini la notion de langage de programmation et précisé son rôle, nous passerons en revue les principales caractéristiques de ce dernier, ce qui nous amènera à une classification de ces langages. 2.1 DÉFINITION ET RÔLE DES LANGAGES On désigne par langage tout système de signes vocaux (parole) ou graphiques (écriture) permettant aux humains d’exprimer leur pensée et de communiquer entre eux. Une telle définition fait davantage référence à la notion de langage naturel (ensemble fini de mots formés à partir d’un alphabet, suivant une syntaxe stricte et riche en sémantique), dans la mesure où elle implique l’homme plutôt que l’ordinateur dans la manipulation des signes. Les langages de programmation, qui servent à commander les circuits des ordinateurs, s’inspirent de la même réalité : ils permettent à l’homme de communiquer avec la machine. En effet, on appelle langage de programmation, en informatique, un ensemble de signes (ou symboles) et de règles utilisés pour programmer les ordinateurs. La notion de règle est liée à la syntaxe, alors que les symboles constituent l’alphabet du langage. L’utilisateur qui veut transmettre ses ordres à l’ordinateur le fait par l’intermédiaire de langages de programmation. Ces derniers se situent en quelque sorte à mi-chemin entre le langage naturel et le langage machine. En effet, ils sont suffisamment proches des langages naturels pour que les programmes puissent être facilement écrits, compris et modifiés. De plus, ils sont définis avec rigueur, de sorte que les programmes qui les utilisent peuvent être traduits dans le langage machine de n’importe quel ordinateur; il en sera question plus loin. En d’autres termes, un langage de programmation assure une 29 30 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI correspondance entre les opérations énoncées dans les algorithmes et les instructions du programme qui codent ces opérations. L’ensemble des mots formés à partir de l’alphabet constitue le vocabulaire du langage de programmation. 2.2 LES CARACTÉRISTIQUES DES LANGAGES DE PROGRAMMATION Les langages de programmation partagent avec les langages naturels un certain nombre de caractéristiques qui sont de trois ordres : lexicale, syntaxique et sémantique. 2.2.1 Les caractéristiques lexicales Un langage de programmation comprend généralement un certain nombre de symboles constituant son alphabet. Dans le cas d’un langage comme PASCAL, l’alphabet comprend les lettres minuscules, les lettres majuscules, les chiffres, le caractère espace ou « blanc » et divers symboles incluant les signes de ponctuation, les opérateurs et les séparateurs. Comme nous l’avons vu au chapitre précédent, on distingue les opérateurs arithmétiques ( +, –, *, / ), les opérateurs relationnels ou de comparaison ( <, <=, >, >=, = ) et les opérateurs logiques (NOT, AND, OR). Les symboles ( ), [ ] et { } constituent, quant à eux, des séparateurs, au même titre que la virgule, le point-virgule, le point et les deux-points. En plus de son alphabet, un langage de programmation comprend un certain nombre de règles de nature lexicale. Celles-ci spécifient le mécanisme de formation des mots du langage en question. Ainsi, le mot « aberrration », même s’il n’est formé que de lettres appartenant à l’alphabet français, n’est pas un mot de la langue française. En effet, cette langue n’admet pas qu’une même consonne se répète trois fois de suite. Dans tout langage de programmation, on retrouve deux catégories de mots : les mots réservés et les identificateurs. Les mots réservés (ou mots clés), comme leur nom l’indique, sont définis par le langage et toute tentative de redéfinition de la part de l’utilisateur donne lieu à des erreurs dites de compilation, c’est-à-dire des erreurs générées au cours de la traduction du programme source en programme objet. À titre LES LANGAGES DE PROGRAMMATION d’exemple, on peut citer, en PASCAL, le mot BEGIN qui sert à indiquer le début d’un bloc d’instructions et END qui en indique la fin. Quant aux identificateurs, ce sont des mots choisis par le programmeur pour représenter un objet du programme, conformément aux règles lexicales du langage. Par exemple, en PASCAL, un identificateur doit nécessairement commencer par une lettre. Ainsi, « +TARD » ne serait pas un identificateur valide, puisqu’il débute par le symbole « + ». 2.2.2 Les caractéristiques syntaxiques Un langage de programmation est aussi caractérisé par sa syntaxe. En effet, même si tous les mots utilisés dans un programme sont individuellement et lexicalement valides, les instructions ou phrases qui en découlent ne le sont pas nécessairement. Une instruction d’un langage donné est valide ou correcte lorsqu’elle est conforme aux règles grammaticales ou syntaxiques qui définissent ce langage. Il en est ainsi d’ailleurs dans les langages naturels : une phrase est correcte lorsqu’elle respecte la grammaire du langage. Par exemple, la phrase « L’aberration est. » est syntaxiquement incorrecte, car incomplète. La question de conformité grammaticale est intimement liée à la non-ambiguïté des phrases du langage et au respect des règles de dérivation utilisées dans la définition de la grammaire. Par règle de dérivation, on entend un formalisme selon lequel on peut combiner des mots ou symboles pour dériver des instructions ou phrases. Tout programme doit respecter la syntaxe du langage dans lequel il est écrit. On comprendra dès lors que l’oubli d’un simple mot ou même d’un caractère dans une instruction donne lieu à des erreurs de compilation. Ce qui contribue à rendre fastidieuse la tâche de mise au point d’un programme. 2.2.3 Les caractéristiques sémantiques Un langage de programmation sert essentiellement à commander les circuits électroniques qui composent un ordinateur, afin d’obtenir la réponse à un problème donné. Ce dernier est préalablement résolu à travers un algorithme indiquant la séquence des 31 32 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI opérations à effectuer. Le programme qui en résulte correspond donc à une suite d’instructions dont le sens doit rester équivalent à l’ensemble des étapes de l’algorithme codé. D’où la nécessité pour un langage de programmation de recourir à des instructions suffisamment significatives en regard des opérations à effectuer. Ainsi, en PASCAL, l’instruction de lecture est READ, celle d’écriture, WRITE. Notons que les termes anglais READ et WRITE ont pour traduction française LIRE et ÉCRIRE respectivement. Idéalement, un langage de programmation devrait être le plus proche possible du langage naturel. Cependant, il n’en est pas toujours ainsi dans la réalité; ceci nous conduit à classifier les langages de programmation selon leur proximité du langage naturel. 2.3 LA CLASSIFICATION DES LANGAGES DE PROGRAMMATION En référence à leur proximité du langage naturel, les langages de programmation sont répartis en deux catégories : les langages de bas niveau et les langages de haut niveau. Il importe de caractériser chacune de ces catégories, pour ensuite traiter des nouveaux développements dans ce domaine. 2.3.1 Les langages de bas niveau Les langages de bas niveau sont plus proches de la machine que de l’homme. Ils regroupent les langages machines et les langages d’assemblage ou assembleurs. Le langage machine À l’origine, l’écriture d’un programme se faisait en langage machine, à partir d’un alphabet binaire, d’où l’appellation équivalente de langage de première génération. Ainsi, le codage de n’importe quel algorithme simple se révélait une tâche fastidieuse au cours de laquelle, ne serait-ce que par distraction, il était facile de se tromper en plaçant dans la chaîne de bits d’une instruction, par exemple, un zéro (0) à la place d’un un (1). La figure 2.1 présente un exemple typique d’un segment de programme écrit en langage machine pour calculer la somme de deux nombres. LES LANGAGES DE PROGRAMMATION 000100000000 01011000 001100010000000000100100 000100000001 01010011 001100010000000000101000 000100000010 01010000 001100100001000001000000 FIGURE 2.1 PROGRAMME D’ADDITION EN LANGAGE MACHINE. Pour des raisons de lisibilité, on peut être amené à changer la base de numération. Ainsi, la figure 2.2 reproduit le même segment de programme, cette fois-ci dans le système hexadécimal (base 16). 100 58 310024 101 53 310028 102 50 321040 FIGURE 2.2 CODAGE EN SYSTÈME HEXADÉCIMAL. Il existe autant de langages machines que de marques d’ordinateurs, selon le type de processeur dont ceux-ci peuvent être munis, ce qui ne facilite pas les choses. En effet, cela exige du programmeur qu’il connaisse, pour chaque processeur, tous les codes binaires représentant les instructions et qu’il sache exactement à quelle adresse de mémoire, exprimée en binaire, se trouvaient les données. C’est, de toute évidence, un énorme travail de codage qui incombe à chaque fois au programmeur. Les langages machines sont donc considérés comme des langages de programmation de première génération. Par ailleurs, la plupart des utilisateurs considèrent l’ordinateur comme un outil destiné à faciliter la résolution de leurs problèmes. La programmation en langage machine les oblige non seulement à connaître le fonctionnement de l’outil dans les moindres détails, mais aussi les amène souvent à consacrer plus de temps à la conception de leurs programmes qu’à la détermination de l’algorithme de résolution. Le langage machine apparaît donc, de tous les langages de programmation, comme celui qui est le plus éloigné des problèmes à résoudre et le moins expressif. 33 34 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI Le langage d’assemblage Pour pallier les inconvénients manifestes du langage machine, on a eu recours au langage d’assemblage. Le langage d’assemblage est une forme symbolique du langage machine : alors que ce dernier est essentiellement numérique, le langage d’assemblage, quant à lui, fait appel à des noms symboliques de type plutôt alphabétique pour désigner les codes d’opération et les opérandes en mémoire. Aussi l’appelle-t-on langage de deuxième génération. La figure 2.3 illustre un segment de programme écrit en langage d’assemblage pour additionner deux nombres. LDA X (Charger le nombre X dans la cellule A) ADD Y (Ajouter le nombre Y au contenu de cette cellule) STA Z (Sauvegarder le résultat dans la cellule Z) FIGURE 2.3 PROGRAMME D’ADDITION EN LANGAGE D’ASSEMBLAGE. Comme tout langage de programmation, les langages d’assemblage possèdent une syntaxe qui doit être respectée lors du codage de l’algorithme. Ils constituent la seconde génération des langages de programmation. 2.3.2 Les langages de haut niveau Les multiples inconvénients des langages de bas niveau ont amené les spécialistes de l’informatique à définir une autre catégorie de langages plus proches du langage humain : ce sont les langages de haut niveau ou de troisième génération. Ils sont appelés ainsi en raison de leur définition théoriquement indépendante de l’ordinateur sur lesquels ils sont implantés. Dans cette catégorie, on retrouve les langages évolués destinés à des applications variées et les langages spécialisés qui, comme leur nom l’indique, ne se prêtent qu’à certains types d’application. Parmi les langages évolués les plus utilisés actuellement, on peut citer : FORTRAN, BASIC, COBOL, PASCAL et C. Pour ce qui est des langages spécialisés, mentionnons SIMULA et GPSS. Dans cette section, nous allons passer en revue ces différents langages, ainsi que les notions de génération de langages de programmation et de machine-langage. LES LANGAGES DE PROGRAMMATION Le langage FORTRAN Le langage FORTRAN (FORmula TRANslation) a vu le jour en 1957. Premier langage de haut niveau, il a été spécialement conçu pour les applications scientifiques et d’ingénierie. Actuellement, il existe plusieurs versions de ce langage, la plus récente étant le FORTRAN 77. En outre, il peut être utilisé par une variété de systèmes informatiques. FORTRAN répond bien aux exigences d’un langage évolué. En effet, il permet de coder de manière plus naturelle les opérations qui doivent être exécutées par l’ordinateur. À titre d’exemple, l’addition de deux nombres peut être réalisée par l’instruction FORTRAN suivante : SOMME = X + Y Reçu avec méfiance par la communauté informatique, ce langage avait rendu moins laborieuse la tâche de mise au point des programmes. Aussi, revient-il à FORTRAN le mérite d’avoir été le premier langage utilisé sur plusieurs ordinateurs de fabricants différents : c’est donc le premier langage indépendant de la machine. FORTRAN reste néanmoins un langage fort peu recommandé pour les ordinateurs personnels, car trop encombrant. Le langage COBOL Le langage COBOL (COmmon Business-Oriented Language) est apparu en 1959, en réponse à des besoins de traitement de données commerciales. C’est donc essentiellement un langage adapté aux applications de gestion. Il a été conçu pour que son utilisation soit indépendante du type d’ordinateur. COBOL possède deux caractéristiques fondamentales. D’abord, il offre à ses utilisateurs la possibilité d’écrire des programmes en employant des expressions très proches des langages naturels. Par exemple, l’addition de deux nombres en COBOL pourrait correspondre à l’instruction suivante : ADD X TO Y GIVEN Z 35 36 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI Ensuite, il accorde à la description des données une place aussi grande que celle qui est réservée aux instructions exécutables du programme. Enfin, si COBOL accuse un certain retard quant à la concision du langage, il se révèle par contre nettement en avance pour ce qui est de la prise en compte des données. Cette attention portée aux données présageait déjà des préoccupations modernes : définir le mieux possible ce sur quoi va porter le traitement algorithmique. Tout comme le FORTRAN, COBOL s’accommode mal des ordinateurs personnels, en raison principalement de la taille de son compilateur qui doit résider en mémoire principale lors de son utilisation. Le langage BASIC BASIC (Beginners All-purpose Symbolic Instruction Code) a été introduit en 1965. C’est un langage de haut niveau qui convient aussi bien aux applications de gestion qu’à celles d’ingénierie ou de type scientifique. Même si à l’origine il était conçu particulièrement pour les systèmes à temps partagé, il est aujourd’hui très populaire sur les ordinateurs personnels, fonctionnant essentiellement en monoprogrammation. Sur le plan syntaxique, il demeure assez proche du FORTRAN et procède du même souci de concision dans le codage des opérations. Par exemple, l’addition de deux nombres en BASIC donnerait lieu à l’instruction suivante : 250 Z = X + Y dans laquelle 250 n’est autre que le numéro de ligne où se trouve l’instruction. BASIC est un langage très populaire auprès des programmeurs débutants. Son utilisation s’est de beaucoup accrue avec l’avènement des ordinateurs personnels sur lesquels il en existe toujours une version. Le langage PASCAL Le langage PASCAL, qui tient son nom de l’écrivain et philosophe français Blaise Pascal, a fait son apparition en 1972. C’est un langage évolué, conçu par N. Wirth, dont LES LANGAGES DE PROGRAMMATION les domaines d’application sont la gestion, la science, l’ingénierie et l’éducation. Il s’est d’abord développé dans la communauté scientifique, particulièrement dans les universités. Actuellement, il est l’un des langages les plus utilisés en éducation et particulièrement sur les ordinateurs personnels. Le PASCAL est un langage facile à apprendre et qui se prête bien à l’enseignement. De plus, il permet d’écrire des programmes structurés et faciles à lire. La manipulation des données et des fichiers s’y réalisent aisément. Contrairement aux langages évolués déjà vus, une instruction en PASCAL a un format très souple : il n’y a donc pas de zones prédéterminées ni de numéros de colonne pour la placer. Enfin, il convient de noter que, par sa structure et sa philosophie de conception, PASCAL demeure un ancêtre de bien des langages de programmation moderne, dont ADA et MODULA. Le langage C Le langage C (après B) est un langage de programmation à but général, qui a fait son apparition en 1972. Ses concepteurs n’ont pas voulu, à proprement parler, en faire un langage de très haut niveau, encore moins un langage spécifique à un domaine d’application particulier. Toutefois, son absence de restrictions alliée à sa généralité lui donne toutes les propriétés d’un puissant langage de haut niveau. C’est donc un langage qui est recommandé à la fois pour les applications scientifiques, d’ingénierie et de développement de logiciel. Aussi, est-il souvent utilisé pour la programmation de systèmes d’exploitation, de systèmes de base de données et de traitement de texte. Le langage C est un langage moderne, qui se prête merveilleusement à la programmation modulaire. C’est la raison pour laquelle les programmes écrits dans ce langage sont faciles à maintenir et transportables. Ainsi, deux programmes écrits en C, peu importent les données soumises, fourniront des résultats identiques sur deux machines différentes. Des versions sont disponibles pour des ordinateurs de toute taille. Même si C est un langage évolué suffisamment général, certaines de ces instructions demeurent proches de la machine. Dans ce sens, il apparaît comme un compromis entre les langages d’assemblage et les langages de haut niveau. 37 38 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI Le langage GPSS Le GPSS (General Purpose Simulation System) est le premier langage mis au point pour simuler par ordinateur des événements tels que les arrivées de bateaux dans les ports, le contrôle de la circulation dans les villes, dans les aéroports, les hôpitaux, etc. Il fut commercialisé par IBM en 1961 et reste encore très utilisé aujourd’hui, comme langage spécialisé de simulation. La modélisation de phénomènes d’attente, faisant appel à des notions de probabilité et de statistiques, se fait très bien avec le langage GPSS. En effet, ce dernier contient des instructions à la fois puissantes et simples pour indiquer l’intervalle de temps séparant la génération de deux transactions (GENERATE) ou la moyenne et l’écart du temps écoulé entre deux services (ADVANCE). Le langage SIMULA Le langage SIMULA apparut en 1967. C’est un langage spécialisé, principalement utilisé pour programmer des applications de type simulation. Plus puissant et plus riche que le GPSS, il prend comme base de départ le langage ALGOL 60, et sa caractéristique principale est la structure de blocs (présente aussi en PASCAL) ou de classes qui en est la généralisation. Un bloc ou classe en SIMULA a le format suivant : BEGIN Déclaration Instruction END; SIMULA, en tant que langage spécialisé, est aujourd’hui encore assez utilisé. La richesse de sa structure en fait un langage très approprié pour la programmation et le traitement de files d’attente, lors de la simulation d’événements de toutes sortes. Les langages de quatrième génération De nos jours, le domaine des langages de programmation est très actif. En effet, on observe à travers le monde une intense activité de recherche et de conception de LES LANGAGES DE PROGRAMMATION nouveaux langages, devant répondre à des besoins aussi bien généraux que spécifiques. Qu’il s’agisse de langages évolués à buts généraux ou de langages spécialisés, ils sont tous considérés comme des langages de haut niveau, faisant partie d’une même génération de langages de programmation : la troisième, après les langages machines et les langages d’assemblage. Ils se caractérisent tous par le fait qu’ils sont conceptuellement indépendants des ordinateurs sur lesquels ils sont implantés et relativement proches du langage humain. D’où la nécessité de recourir à un traducteur (compilateur ou interpréteur) pour la conversion des énoncés de programme en instructions du langage machine. On a observé au cours de la décennie 80 l’émergence de langages de programmation dits de quatrième génération. Ces langages ont pour caractéristique principale d’être directement associés à leur domaine d’application. Ainsi, un programmeur qui doit développer un logiciel destiné à des transactions bancaires aurait besoin idéalement d’un jeu d’instructions sémantiquement représentatives des fonctions de base du domaine. On peut penser à des instructions telles que OPEN pour ouvrir un compte, DEPOSIT pour effectuer un dépôt, WITHDRAW pour effectuer un retrait, CLOSE pour fermer un compte. Il va de soi que les instructions des langages de quatrième génération sont de type impératif (quoi faire), plutôt qu’algorithmique (comment faire). Les langages de manipulation de données comme SQL (Structured Query Language), les environnements statistiques SPSS (Statistical Package for the Social Sciences) et SAS (Statistical Analysis System), ainsi que les générateurs de programmes en sont des exemples. Ces langages sont généralement plus conviviaux et plus faciles à utiliser que les autres. Toutefois, ils n’ont pas réussi à déloger les langages de troisième génération dont la prédominance est nette en tant qu’outil généralisé de résolution de problème. 2.3.3 Les machines-langages Il existe actuellement une certaine tendance à construire des machines-langages. On désigne par machine-langage un ordinateur ayant pour langage de base un langage donné, autre que le langage machine. Les machines-Lisp et les machines-Prolog en sont des exemples. Avec une machine-langage, la traduction préalable à l’exécution devient une fonction matérielle, plutôt que logicielle. Un tel ordinateur n’a donc pas besoin de traducteur 39 40 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI pour convertir les programmes écrits dans son langage de base (programme source) en programmes en langage machine (programme objet). Ceci permet de gagner en temps d’exécution, mais aussi de perdre en flexibilité, puisqu’on ne peut guère utiliser d’autres langages sur la machine en question. C’est avec l’essor de l’intelligence artificielle que sont apparues de telles machines. Elles étaient conçues de manière à satisfaire de nouvelles contraintes de rapidité basées, non plus sur le nombre d’instructions par seconde (IPS), mais plutôt sur le nombre d’inférences logiques par seconde (LIPS). Tout compte fait, l’atteinte de tels objectifs semble de plus en plus liée à la définition de nouvelles architectures d’ordinateur, rompant fondamentalement avec celle de von Neumann. L’avenir de l’intelligence artificielle en général et celle du traitement automatique des connaissances en particulier en dépendent. 2.4 LES TYPES DE PROGRAMMATION En plus de leur proximité du langage naturel, une autre façon de classifier les langages consiste à les regrouper selon le type de programmation qu’ils permettent de réaliser. Ce qui nous amène à distinguer la programmation procédurale, la programmation fonctionnelle, la programmation logique et la programmation par objets. 2.4.1 La programmation procédurale La programmation procédurale, comme son nom l’indique, est étroitement liée à la notion de procédure. On appelle procédure toute séquence d’instructions, formant un tout cohérent auquel on donne un nom, et dont l’exécution peut être demandée de plusieurs endroits d’un programme appelant. Ce dernier communique en général avec la procédure par des paramètres, et son exécution est suspendue tant que celle de la procédure n’est pas terminée. Dans ce contexte, on distingue deux sortes de procédures : – les procédures sous-programme dont l’appel est considéré comme une instruction du langage de programmation; LES LANGAGES DE PROGRAMMATION – les procédures fonction, dont l’appel ne fait que retourner une valeur éventuellement attribuable à une variable. Nonobstant cette distinction, les notions de procédure et de fonction renvoient au concept de module qui a été étudié au chapitre précédent et qui sert de base à la programmation structurée et descendante. Et le terme programmation procédurale désigne la technique de programmation consistant à indiquer à l’ordinateur la séquence d’instructions ou d’ordres à exécuter en vue de résoudre un problème donné. Ainsi, un programme écrit dans un langage procédural ou impératif transmet une liste d’instructions à une machine qui doit les exécuter dans un ordre bien défini pour produire le résultat cherché. Les langages les plus populaires actuellement dans l’industrie sont de type procédural. On peut citer, entre autres, FORTRAN, COBOL, BASIC, PASCAL et C. En programmation procédurale, certaines structures de données comme les listes, les arbres et les graphes sont exprimées dans une structure prédéfinie appelée enregistrement ou article. Aussi, doit-on spécifier avec une telle structure comment ajouter et retrancher des éléments. C’est donc un inconvénient qui justifie le recours à la programmation fonctionnelle. 2.4.2 La programmation fonctionnelle Le concept de programmation fonctionnelle repose sur la notion mathématique de fonction, d’où la nécessité de définir cette dernière. Considérons l’expression : (x + 1) Chaque fois qu’on remplace x par un nombre entier et qu’on évalue l’expression, on obtient un nombre unique. Cette expression peut être assimilée à la machine de la figure 2.4 qui, pour tout élément x soumis en entrée, en produit le successeur. x FIGURE 2.4 MACHINE À SUCCESSEURS. SUCC (x + 1) 41 42 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI On peut constater que x et son successeur sont tous deux des entiers naturels. Dans le langage mathématique, on parlerait d’une fonction Succ de l’ensemble des entiers naturels vers lui-même, notée : Succ: N → N x |→ (x + 1) où x est la variable et (x + 1) la valeur de la fonction. Dans les langages de programmation, on emploie plutôt le terme paramètre en lieu et place de variable qui a une acception particulière. De façon plus concise, on note : Succ(x) = (x + 1) Plus formellement, on peut définir une fonction F par la notation suivante : F: A→ x |→ B F(x) Ce qui se lit : F est une fonction définie dans A à valeur dans B, qui à tout x pris dans A fait correspondre un et un seul F(x) pris dans B. A et B sont respectivement les domaines de départ et d’arrivée de la fonction. Intuitivement, une fonction est une manière d’associer de façon unique des éléments d’un ensemble (de départ) à des éléments d’un autre ensemble (d’arrivée). On peut également définir la composition de fonctions, vulgairement appelée une fonction de fonction. En fait, c’est une fonction dont la variable est elle-même une fonction. Par exemple, le successeur du successeur de x, noté : Succ(Succ(x)) Il existe une fonction particulière, appelée fonction identité et notée I, qui possède la propriété de laisser inchangée la variable qui lui sert d’argument. On peut le définir de la manière suivante : I(x) = x Il reste maintenant à introduire la notion de fonctions réciproques ou inverses. En effet, on dit que deux fonctions F et F’ sont inverses l’une de l’autre, si et seulement si : F(F’(x)) = F’(F(x)) = I(x) LES LANGAGES DE PROGRAMMATION À titre d’exemple, la fonction prédécesseur, notée Pred, est l’inverse de la fonction successeur Succ. Car : Pred(Succ(x)) = Succ(Pred(x)) = x La programmation fonctionnelle consiste à utiliser des langages dont la structure et la syntaxe reposent sur les concepts mathématiques de fonction et de composition de fonctions. Les langages LOGO et LISP en sont des exemples. Dans ce type de programmation, au lieu de décrire les procédures à suivre pour résoudre un problème (comment faire), on spécifie plutôt, au moyen de fonctions, les mécanismes à mettre en œuvre (quoi faire) pour y parvenir. Par exemple, pour construire une liste en LISP, on emploie la fonction CONS dont les paramètres peuvent être soit des éléments simples appelés atomes, soit des sous-listes : CONS((A, B), C) = (A, B, C) Toujours en LISP, on a : CAR(A, B, C) = A CDR(A, B, C) = (B, C) CAR(CDR(A, B, C) = CAR(B, C) = B Les programmes fonctionnels sont en général plus courts, mais plus abstraits que leurs équivalents procéduraux. De plus, ils se prêtent mieux à une analyse et à une manipulation formelles, ce qui en font des programmes relativement faciles à maintenir. Quant aux langages fonctionnels, ils sont dotés d’une grande capacité de traitement symbolique. D’où leur adéquation à résoudre les problèmes d’intelligence artificielle où la manipulation porte sur des données symboliques plutôt que numériques. 2.4.3 La programmation logique Toujours à la recherche de techniques informatiques plus rigoureuses et plus puissantes pour manipuler des connaissances, l’intelligence artificielle en est venue à utiliser la logique comme langage de programmation, ce qui a conduit à un nouveau type relativement simplifié de programmation, baptisé à juste titre programmation logique. Le langage PROLOG, conçu par A. Colmerauer au début des années soixante-dix, en demeure le plus authentique représentant. 43 44 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI La programmation logique s’est développée à partir des clauses de Horn. Ce sont des formules de la forme : (implique) (A1 & A2 & .... & An) → B où les Ai et B sont des termes, c’est-à-dire soit des constantes ou des variables, soit des expressions p(t1,..., tn) dans lesquelles p désigne un prédicat et les ti sont eux-mêmes des termes. Un très grand nombre de connaissances peuvent être décrites de cette manière. Par exemple, la formule qui définit la transitivité des liens de parenté (les parents de nos parents sont nos grands-parents) est une clause de Horn : parent(x, y) & parent(y, z) → grands-parents(x, z) Dans cette formule, parent(x, y) signifie que x est le parent de y. En outre, même une proposition élémentaire, un fait, peut se présenter comme une clause de Horn dont la partie condition est remplacée par la valeur logique VRAI : VRAI → B Voici des données exprimant des relations entre plusieurs individus d’une même famille : VRAI → VRAI → VRAI → VRAI → mère(Laurie, Stéphane) frère(Stéphane, Sabine) père(Samuel, Stéphane) mère(Laurie, Sabine) La programmation logique se fonde sur le principe que programmer, c’est prouver. Elle utilise un mode déclaratif, dans lequel le problème à résoudre est décrit de façon suffisamment précise, mais sans donner explicitement la manière de le résoudre. L’interprète du langage se charge alors de trouver l’ensemble des solutions qui satisfont cette description. Par exemple, si l’on désire connaître les parents de Sabine, il suffit de poser la question : parents(x, Sabine) LES LANGAGES DE PROGRAMMATION et l’on obtiendra l’ensemble des solutions, c’est-à-dire l’ensemble des x qui correspondent à ce but, dans les connaissances exprimées sous forme de clauses de Horn : x = Laurie x = Samuel Imaginons que l’on veuille obtenir l’ensemble des couples (x, y) tels que x est mère de y. Il suffit de poser la question : mère(x, y) et le système affichera : x = Laurie, y = Stéphane x = Laurie, y = Sabine Au début des années 80, les Japonais ont fait part au monde entier de leur ambitieux projet de mise au point d’ordinateurs de la cinquième génération, orientés vers les applications d’intelligence artificielle. Le langage de base retenu pour de telles machines a été PROLOG. Depuis, on observa un regain d’intérêt grandissant pour ce langage. On en a pour preuve la multiplicité des équipes de recherche qui s’y consacrent et la prolifération des versions de ce langage qui, somme toute, se prêtent bien à l’exécution rapide d’inférences logiques. 2.4.4 La programmation par objets La programmation par objets, comme son nom l’indique, repose sur la notion d’objet. On retrouve dans la littérature plusieurs termes qui s’apparentent à ce concept. En effet, dans les travaux sur la mémoire en psychologie cognitive, on parle souvent de schéma. Dans le domaine du traitement des langages naturels, on emploie tour à tour les termes frame, script et prototype, les deux premiers n’ayant pas d’équivalents français. De nos jours, le parti semble être pris pour utiliser le terme objet dont la connotation s’avère bien la plus générale. On désigne par objet une structure de connaissances constituée d’un certain nombre d’aspects ou d’attributs. Ces derniers ne sont autres que les noms des propriétés qui caractérisent l’objet. Par exemple, un objet Employé peut admettre pour attributs Nom, 45 46 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI Sexe, Âge, Adresse, Profession et Numéro. De plus, à chaque aspect on peut associer des facettes telles que valeurs-possibles qui définit le domaine des valeurs que peut prendre cet aspect, ou valeurs-défaut qui spécifie la valeur par défaut de celui-ci. Ainsi, on peut attribuer à Âge la valeur par défaut 45. Les langages orientés objets sont devenus depuis quelques années un outil de base de la représentation des connaissances en intelligence artificielle. Ils possèdent deux propriétés fondamentales. D’abord, ils rendent possible la description d’objets hiérarchisés, avec transmission de propriétés en provenance des parents. D’autre part, ils permettent dans une certaine mesure de tirer parti des avantages de la programmation procédurale, par le biais des attachements procéduraux, appelés démons, intégrés aux objets. Par exemple, un Employé cadre, ayant Employé pour parent dans une hiérarchie, peut être décrit par les attributs suivants : Nom, Sexe, Adresse, Âge, Fonction. Chacun de ces attributs peut avoir une valeur et une valeur par défaut. La valeur de l’attribut Âge peut être prise égale à 45, par transmission de la valeur par défaut de son parent Employé. On peut également avoir une facette appelée Salaire, qui est en fait un démon permettant de calculer le salaire de cet employé cadre. SMALLTALK, considéré comme un dérivé du langage SIMULA, est le premier véritable langage orienté objet qui a été mis au point. Dans ce langage, tout est objet et tout objet se définit à la fois par son état (les attributs statiques) et par les opérations qu’on lui applique (les attributs dynamiques). Les attributs statiques correspondent en réalité à de simples champs (d’un enregistrement). SMALLTALK intègre les concepts de méthode (démon) et de communication par échange de messages. On y retrouve également les concepts d’instance (fils) et de classe (parent) qui caractérise une hiérarchie. Une instance appartient à une classe dont elle hérite des propriétés et des opérations définies pour cette classe. SMALLTALK est actuellement disponible sur des machines de plus en plus nombreuses. La vogue des langages orientés objets dépasse le simple phénomène SMALLTALK. De très nombreux langages faisant explicitement référence aux mêmes concepts sont disponibles ou apparaissent actuellement. On peut citer, entre autres, LOOPS, C++, VISUAL BASIC, PASCAL OBJET et FLAVORS. Ces langages ont des champs d’application très divers, mais ils ressemblent tous, sous certains aspects, à SMALLTALK.