tag:linuxfr.org,2005:/tags/langage_progammation/publicLinuxFr.org : les contenus étiquetés avec « langage_progammation »2020-09-10T18:53:56+02:00/favicon.pngtag:linuxfr.org,2005:Diary/393292020-09-09T23:46:48+02:002020-09-10T08:26:00+02:00Psychologie d'un parseur JavascriptLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li>
<a href="#toc-un-constat-choquant">Un constat choquant</a><ul>
<li><a href="#toc-pourquoi-%C3%A7a-plante">Pourquoi ça plante</a></li>
</ul>
</li>
<li><a href="#toc-un-d%C3%A9but-de-piste">Un début de piste</a></li>
<li><a href="#toc-comment-analyse-t-on-un-expression-javascript">Comment analyse-t-on un expression Javascript ?</a></li>
<li>
<a href="#toc-diff%C3%A9rences-de-comportement-des-moteurs-javascript">Différences de comportement des moteurs Javascript</a><ul>
<li><a href="#toc-v8">V8</a></li>
<li><a href="#toc-spidermonkey">SpiderMonkey</a></li>
<li><a href="#toc-rhino">Rhino</a></li>
<li><a href="#toc-javascriptcore">JavascriptCore</a></li>
</ul>
</li>
<li>
<a href="#toc-dans-dautres-langages">Dans d'autres langages</a><ul>
<li><a href="#toc-java-jshell-openjdk">Java (JShell, OpenJDK)</a></li>
<li><a href="#toc-c---clang">C - Clang</a></li>
<li><a href="#toc-c---gcc">C - GCC</a></li>
<li><a href="#toc-c---tiny-c-compiler">C - Tiny C Compiler</a></li>
</ul>
</li>
<li><a href="#toc-mot-de-la-fin">Mot de la fin</a></li>
</ul>
<p>(attention : beaucoup de suppositions, peu de vérifications dans ce journal. Lisez pour le cheminement plus que pour le résultat…)</p>
<h2 id="toc-un-constat-choquant">Un constat choquant</h2>
<p>De manière tout à fait intéressante en Javascript :</p>
<pre><code class="js"><span class="o">++</span> <span class="o">++</span> <span class="nx">i</span><span class="p">;</span></code></pre>
<p>Donne l'erreur suivante dans Node (V8):</p>
<pre><code>SyntaxError: Invalid left-hand side expression in prefix operation`
</code></pre>
<p>Et, dans Firefox (SpiderMonkey):</p>
<pre><code>SyntaxError: expected expression, got '++'
</code></pre>
<p>Alors que :</p>
<pre><code class="js"><span class="nx">i</span> <span class="o">++</span> <span class="o">++</span><span class="p">;</span></code></pre>
<p>Donne l'erreur suivante dans les deux moteurs (à quelque chose près) :</p>
<pre><code>SyntaxError: Unexpected token '++'
</code></pre>
<p>De quoi rester rêveur, vous ne trouvez pas ? L'erreur semble être symétrique, alors pourquoi donc une telle asymétrie dans les message d'erreur, une telle différence ? Abasourdissant, non ?</p>
<h3 id="toc-pourquoi-ça-plante">Pourquoi ça plante</h3>
<p>Ah oui, au fait, présentons rapidement quelques bases de ce problème.</p>
<ul>
<li>
<code>++i</code> est une pré-incrémentation. Elle est censée prendre <code>i</code>, lui ajouter 1, enregistrer la valeur dans <code>i</code> et retourner le résultat de cette opération. <code>--i</code> fonctionne pareil, mais retire 1.</li>
<li>
<code>++ ++i</code> devrait faire la même chose, puis… comme <code>++i</code> n'est pas une référence, le premier <code>++</code> ne peut enregistrer son résultat nulle part. En fait, l'expression n'a pas vraiment de sens, à tel point que c'est une erreur de syntaxe.</li>
<li>
<code>i++</code> est censé prendre <code>i</code>, lui ajouter 1, enregistrer la valeur dans <code>i</code> et retourner la valeur originale de <code>i</code>. <code>i--</code> fait pareil mais retire 1.</li>
<li>
<code>i++ ++</code> a à peu près le même sens que <code>++ ++i</code>, c'est à dire aucun.</li>
</ul>
<p>Donc ça plante. Mais pourquoi ça ne plante pas exactement de la même manière ?</p>
<h2 id="toc-un-début-de-piste">Un début de piste</h2>
<p>C'est certainement parce quand on analyse une expression Javascript, qu'on a besoin de pouvoir accepter plusieurs opérateurs préfixes, alors qu'on n'a pas besoin d'accepter plusieurs opérateurs suffixes.</p>
<p>Voyez plutôt ces expressions valides en Javascript :</p>
<pre><code>+ ++i
- ++i
+ - + - i
- + - + i
+ + i
- - i
void typeof void + -- i
</code></pre>
<p>On peut chaîner des opérateurs préfixes à l'infini ! Alors qu'on ne peut pas en dire autant de l'opérateur suffixe.</p>
<h2 id="toc-comment-analyse-t-on-un-expression-javascript">Comment analyse-t-on un expression Javascript ?</h2>
<p>Pour nous former une intuition pas trop pourrie de la situation, imaginons un peu comment on peut analyser une expression Javascript (ou Java, ou C, d'ailleurs, le problème est le même. Pour les gens qui ne connaissent pas ces langages, imaginez une expression arithmétique classique comme celles qu'on voit au collège, mais avec ces fameux opérateurs préfixes et suffixes).</p>
<p>Comment peut-on analyser une telle expression alors ? On pourrait aussi bien lire le code des différents moteurs Javascript, ou <a href="https://www.ecma-international.org/ecma-262/#sec-ecmascript-language-scripts-and-modules">lire la doc, tant qu'à faire</a>, Javascript étant un langage extrêmement bien spécifié avec une spécification largement exploitable. Mais déjà, lire ces codes ou même cette spec n'est pas trivial, et ensuite, pour des raisons totalement égoïstes, j'ai envie de réfléchir au problème d'analyser une expression Javascript avant de regarder les solutions existantes ou suggérées. Alors allons-y gaiement. </p>
<p>On a vu qu'il pouvait y avoir une infinité d'opérateurs préfixes. Ces opérateurs sont ensuite suivis d'une expression sans opérateur. Éventuellement, il y a un opérateur suffixe. Puis, l'expression s'arrête, ou alors il y a un opérateur infixe puis le début d'une nouvelle expression (c'est « récursif »). </p>
<p>Un pseudo code correspondant à cette idée, générant un arbre d'analyse syntaxique à partir d'une expression Javascript (sous forme de chaîne de caractères ou de token), pourrait être le suivant (attention, je ne garantis pas que c'est correct, je n'ai pas encore testé) :</p>
<pre><code># tokenStream est l'expression javascript en entrée qu'on analyse
# Cette liste va contenir les opérateurs et les expressions javascript sans opérateurs.
list := [];
begin:
# On récupère zéro, un ou plusieurs opérateurs préfixes
infinite loop {
op := parsePrefixOp(tokenStream);
if (op) {
list.push(op);
} else {
break;
}
}
# On récupère une expression JS sans opérateurs
list.push(parseOperatorFreeExpression(tokenStream))
# NOTE: S'il n'y en a pas, on lève une erreur de syntaxe et on s'arrête
# On récupère au plus un opérateur suffixe.
op := parseSuffixOp(tokenStream);
if (op) {
list.push(op);
}
# NOTE: si on a trouvé un opérateur suffixe, on peut tout de suite lever une erreur ici si le dernier opérateur analysé est un opérateur ++ ou --, ou alors décider de traiter ça plus tard, lors de la résolution des priorité opératoires par exemple.
# On peut même avoir écrit le parseur d'une façon que si un -- ou un ++ est trouvé, un code différent, sans analyse des opérateurs suffixes, soit utilisé !
# On récupère au plus un opérateur infixe
op := parseInfixOp(tokenStream);
if (op) {
list.push(op);
# Si on en a trouvé un, on recommence
goto begin;
}
# On est arrivé à la fin de la chaîne, on va résoudre les priorités opératoires et construire l'arbre d'analyse syntaxique en conséquence.
return resolveOperatorPriorities(list)
</code></pre>
<p>On peut commencer à voir pourquoi les erreurs sont différentes entre <code>++ ++ i</code> et <code>i ++ ++</code>. Il y a fort à parier que l'erreur de syntaxe n'est pas levée exactement au même endroit.</p>
<p>Dans le cas <code>i ++ ++</code>, il est possible que le deuxième <code>++</code> ne soit même pas compris comme l'opérateur de post incrémentation : on ne les cherche pas à cet endroit puisqu'on ne cherche qu'un opérateur suffixe au maximum.</p>
<p>Alors que dans le cas <code>++ ++ i</code>, il est fort probable qu'une sorte de boucle essaie de manger tous les opérateurs préfixes jusqu'à rencontrer une expression Javascript non préfixée. C'est seulement plus tard, quand le parseur va trouver qu'il y a quelque chose qui n'est pas « incrémentable » (un référence, quoi - qui peut d'ailleurs être entre parenthèse 🙃), qu'il va râler.</p>
<h2 id="toc-différences-de-comportement-des-moteurs-javascript">Différences de comportement des moteurs Javascript</h2>
<p>Est-ce que les moteurs Javascript analysent les expressions de la même manière, d'ailleurs ?</p>
<p>On peut vite le découvrir sans lire leur code source (ce qui doit être très intéressant, mais ce n'est pas l'objet de ce journal). Dans le shell Javascript interactif de Node comme dans celui la console Web de Firefox, si vous ne terminez pas une instruction Javascript, l'interface vous laisse la continuer même après être passé à la ligne si l'interpréteur Javascript n'a pas encore vu d'erreur de syntaxe. Ce qui permet de deviner des choses sur leur manière d'analyser le code. Essayons avec <code>-- -- i</code>, tiens…</p>
<h3 id="toc-v8">V8</h3>
<p>Si vous tapez <code>-- -- i</code> dans Node et que vous passez à la ligne, pour lui, l'expression n'est pas encore terminée et il vous laisse taper un identificateur ou un opérateur avant de s'apercevoir qu'il y a anguille sous roche. Pire que ça, il vous laisse continuer encore un peu si vous tapez un opérateur suffixe. Autrement dit, l'expression n'est pas terminée pour lui après avoir tapé <code>-- -- i --</code>.</p>
<pre><code>$ node
Welcome to Node.js v14.7.0.
Type ".help" for more information.
> -- -- i --
... ;
-- -- i --
^^^^
Uncaught SyntaxError: Invalid left-hand side expression in prefix operation
</code></pre>
<p>Et d'ailleurs, il donne une erreur sur <code>i --</code> et pas avant. Tout porte à croire qu'il lève l'erreur lors de la résolution des priorités opératoires et qu'éventuellement, il parcourt sa liste de la fin vers le début.</p>
<h3 id="toc-spidermonkey">SpiderMonkey</h3>
<p>Si vous tapez <code>-- --i</code> puis entrée (en fait, vous devrez rajouter une espace avant l'entrée parce que l'autocomplétion propose <code>if</code>), vous vous prenez immédiatement un message d'erreur. SpiderMonkey n'essaierai même pas de lire une suite éventuelle de l'expression. D'ailleurs, si vous lui faites manger <code>-- -- i --</code>, il va continuer à planter sur le caractère 3, contrairement à V8 :</p>
<pre><code>$ gjs
gjs> -- -- i --
typein:1:3 expected expression, got '--':
typein:1:3 -- -- i --
typein:1:3 ...^
@<stdin>:1:42
</code></pre>
<p>On peut penser qu'il détecte assez tôt dans l'analyse de l'expression la présence d'un opérateur préfixe alors qu'un opérateur ++ ou—est déjà présent juste avant.</p>
<h3 id="toc-rhino">Rhino</h3>
<p>Rhino, c'est le moteur Javascript écrit en Java, par Mozilla aussi, et qui a d'ailleurs été embarqué par Sun dans Java SE 6 pour ajouter des capacités de scripting à Java. </p>
<pre><code>$ rhino
Rhino 1.7.7.1
js> -- -- i ++
js: "<stdin>", line 2: erreur de syntaxe
js: -- -- i ++
js: ....^
</code></pre>
<p>Bon bah à tous les coups, il se comporte à peu près pareil que SpiderMonkey dans ce cas. D'ailleurs, un commentaire dans le code de son parseur, <a href="https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/Parser.java">un petit fichier de 4000 lignes</a>, écrit à la main comme tous les bons vrais parseurs (<a href="https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y">sauf celui de PHP</a> écrit avec une belle grammaire Yacc bien propre), dit « It is based on the SpiderMonkey C source files jsparse.c and jsparse.h in the jsref package ».</p>
<p>Et si le monde des moteurs Javascript vous passionne, <a href="https://github.com/mozilla/rhino/blob/master/src/">le code de Rhino</a> semble plutôt accessible, en tout cas probablement plus que ses potes, avec peu d'abstractions : c'est du code assez direct qui n'y va pas par 4 chemins.</p>
<h3 id="toc-javascriptcore">JavascriptCore</h3>
<p>Et le moteur JS de WebKit alors ?</p>
<pre><code>$ seed
> -- ++ i ++
..
..SyntaxError The prefix-decrement operator requires a reference expression.
</code></pre>
<p>Lui aussi semble lever l'erreur assez tôt puisqu'il râle sur le premier opérateur…</p>
<p>Voilà. On dirait que V8 est un peu différent de ses potes dans sa manière d'analyser les expressions Javascript, en tout cas sur cet aspect.</p>
<h2 id="toc-dans-dautres-langages">Dans d'autres langages</h2>
<h3 id="toc-java-jshell-openjdk">Java (JShell, OpenJDK)</h3>
<pre><code>$ jshell [0]
| Welcome to JShell -- Version 11.0.8
| For an introduction type: /help intro
jshell> int i = 0;
i ==> 0
jshell> ++ ++ i ++;
| Error:
| unexpected type
| required: variable
| found: value
| ++ ++ i ++;
| ^--^
</code></pre>
<p>Ce n'est pas super clair, mais ça semble fonctionner au moins un peu comme V8.</p>
<h3 id="toc-c---clang">C - Clang</h3>
<pre><code>$ clang t.c
t.c:1:24: error: expression is not assignable
int main() { int i; ++ ++ i ++; }
^ ~~~~
</code></pre>
<p>Clang nous dit qu'il ne peut pas vraiment pré-incrémenter le résultat d'une post-incrémentation donc ça ressemble un peu au comportement de V8.</p>
<h3 id="toc-c---gcc">C - GCC</h3>
<pre><code>$ gcc t.c
t.c: In function ‘main’:
t.c:1:24: error: lvalue required as increment operand
1 | int main() { int i; ++ ++ i ++; }
| ^~
</code></pre>
<p>Là, j'ai vaguement l'impression qu'il s'attend à avoir une <code>lvalue</code> (c'est à dire un truc qui peut se placer à gauche d'un signe égal, une variable quoi) à l'endroit pointé, donc ça marcherait un peu comme SpiderMonkey : il veut un truc qu'il peut pré-incrémenter à la suite du premier opérateur de pré-incrémentation.</p>
<h3 id="toc-c---tiny-c-compiler">C - Tiny C Compiler</h3>
<pre><code>$ tcc t.c
t.c:1: error: lvalue expected
</code></pre>
<p>Bon, bah là on n'en saura pas plus.</p>
<h2 id="toc-mot-de-la-fin">Mot de la fin</h2>
<p>On peut espérer que tous les parseurs d'un même langage sortent des arbres d'analyse syntaxique à peu près équivalent. En tout cas, dès qu'il y a des erreurs, on peut voir que les comportements diffèrent…</p>
<p>Au final, ne mettez pas des opérateurs en trop et ça va marcher.</p>
<div><a href="https://linuxfr.org/users/raphj/journaux/psychologie-d-un-parseur-javascript.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/121547/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/raphj/journaux/psychologie-d-un-parseur-javascript#comments">ouvrir dans le navigateur</a>
</p>
raphjhttps://linuxfr.org/nodes/121547/comments.atomtag:linuxfr.org,2005:Bookmark/2292018-08-11T12:13:56+02:002018-08-11T12:13:56+02:00Julia 1.0.0<a href="https://julialang.org/blog/2018/08/one-point-zero">https://julialang.org/blog/2018/08/one-point-zero</a> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/115069/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/scls19fr/liens/julia-1-0-0#comments">ouvrir dans le navigateur</a>
</p>
scls19frhttps://linuxfr.org/nodes/115069/comments.atomtag:linuxfr.org,2005:Post/389732018-02-07T14:43:18+01:002018-02-08T08:44:46+01:00De la conception du langage Python<p>Dans mon journal sur <a href="//linuxfr.org/users/bluestorm/journaux/la-recherche-en-langages-de-programmation-au-quotidien">La recherche en langages de programmation au quotidien</a>, Xavier Combelle demande un avis sur Python—sur les rapports entre Python et la théorie des langages de programmation, j'imagine. J'ai choisi de créer un sujet ici puisque c'est une discussion un peu "hors sujet".</p>
<blockquote>
<p>Quel est ton avis sur mon langage préféré: python auquel je n'ai pas fait défaut depuis sa découverte il y a une dizaine d'année ?</p>
</blockquote>
<p>Je voudrais discuter surtout des aspects qui concernent les aspects linguistiques eux-mêmes (le choix des fonctionnalités du langage, plutôt que des bibliothèques et programmes construits au-dessus), et aussi les aspects de gouvernance sur l'évolution de ce langage et les décisions qui sont prises aujourd'hui ou ont été prises dans le passé.</p>
<p>D'abord j'aimerais commencer par dire des choses qui me plaisent dans Python:</p>
<ul>
<li><p>La gouvernance du projet est bien menée, avec un système de PEP (Python Extension Proposals) installé tôt et qui marche bien.</p></li>
<li><p>La syntaxe de Python est étonnamment sympa. C'est rare de voir un langage qui ressemble autant à ce qu'on écrirait naturellement comme pseudo-code. Je pense que c'est en grande partie lié à un vrai talent de son concepteur principal, Guido Van Rossum, pour trouver une jolie syntaxe. Ça aide pour enseigner Python aux débutants. C'est intéressant parce que la question de "quelle syntaxe est plus jolie/lisible qu'une autre" est une question sur laquelle on a très peu prise, scientifiquement : je ne connais pas de critère objectifs pour s'aider dans ces choix, et je pense que personne ne comprend bien les ingrédients de conception d'une bonne syntaxe.</p></li>
<li><p>Python a une très grosse communauté, vivante, qui apporte beaucoup de choses. Je suis par exemple un grand admirateur du projet <a href="http://www.sagemath.org/">SageMath</a> (anciennement Sage), qui a réussi à fédérer une communauté entière autour d'un projet libre de taille, et du projet <a href="http://jupyter.org/">Jupyter</a> (anciennement <a href="https://ipython.org/">IPython</a>) qui a eu un impact très positif sur les interfaces qu'on utilise pour programmer. Dans les logiciels libres qu'on utilise au jour le jour, beaucoup sont codés en Python, entièrement ou partiellement. (Je suis ravi d'y contribuer si j'en ai l'occasion.)</p></li>
</ul><p>Maintenant quelques critiques :</p>
<ul>
<li><p>Le créateur du langage, Guido Van Rossum, est globalement assez hostile aux idées venant de la programmation fonctionnelle (à part les compréhensions de listes, qui ont plu), et a eu dans le passé une attitude assez fermée vis-à-vis des universitaires du domaine. Ça ne l'intéressait pas de discuter pour comprendre des aspects de Python à améliorer, ce qui est toujours dommage. (Par exemple, il n'y a pas d'appels terminaux en Python, ce qui complique inutilement l'écriture de certains programmes récursifs, alors qu'on sait depuis les années <s>1990</s> 2000 comment combiner appels terminaux et backtraces (<a href="http://digitalcommons.calpoly.edu/csse_fac/48/">A Tail-Recursive Machine with Stack Inspection</a>, John Clements, Matthias Felleisen, 2004), qui est la raison invoquée pour leur absence). Maintenant la gouvernance de l'évolution du langage est plus distribuée, et Guido a peut-être un peu revu sa position, donc les choses se sont améliorées.</p></li>
<li><p>Il y a quelques erreurs de conception qui étaient présentes dès le départ dans le langage et qui viennent d'une ignorance de concepts basiques quand on étudie les langages de programmation. Par exemple, la portée lexicale (la portée des variables avec déclarations imbriquées) est mal conçue, et a nécessité l'ajout du mot-clé <a href="https://www.python.org/dev/peps/pep-3104/">nonlocal</a> (un exemple d'évolution du langage bien menée mais qui aboutit quand même à une solution moche pour un problème qui n'aurait pas dû être là au départ).</p></li>
<li><p>C'est un langage non typé statiquement qui est cependant utilisé pour de gros projets. Personnellement je suis convaincu que les types statiques jouent un rôle essentiel pour permettre la maintenance et le refactoring de code dès qu'on a un projet un peu gros, et je trouve que développer quelque chose comme Django en Python crée des logiciels très difficiles à gérer (même quand on fait un effort considérable sur les tests). Les systèmes de types statiques ne sont pas sans défauts non plus, et le fait d'explorer des idées dans un langage sans typage statique est très raisonnable, mais ça ne produit pas des langages que j'ai envie d'utiliser moi-même, et que je ne pas qu'ils soient adaptés pour de gros projets. (Mais souvent les gros projets commencent petit.) D'ailleurs les efforts actuels pour ajouter du typage après-coup à Python sont majoritairement motivés par ces problèmes de maintenance à grande échelle. Ils sont très difficiles et douloureux—bien plus difficile que si le langage avait été conçu avec du typage dès le départ. Il y a sans doute des gens avec un bagage théorique qui vont se pencher sur la question de proposer un typage de Python après-coup, mais je leur souhaite bien du courage.</p></li>
</ul><p>Voilà, j'ai donné un avis sur Python, mentionnant seulement quelques aspects qui me viennent à l'idée directement. Je pense que c'est important de comprendre qu'aucun langage n'est parfait, et qu'une communauté peut développer des choses de valeurs tout à fait indépendamment des caractéristiques du langage lui-même. Ceci dit, moi j'évite d'écrire du Python sauf pour des petits scripts, et mes expériences de contribution à de plus gros projets dans ce langage (des sites en Django typiquement) m'ont confirmé dans l'impression que ça peut être assez pénible au quotidien de travailler dans un langage non typé sur un gros projet. (Mais ça pourrait être pire, PHP par exemple.)</p><div><a href="https://linuxfr.org/forums/general-hors-sujets/posts/de-la-conception-du-langage-python.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/113692/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/forums/general-hors-sujets/posts/de-la-conception-du-langage-python#comments">ouvrir dans le navigateur</a>
</p>
gaschehttps://linuxfr.org/nodes/113692/comments.atomtag:linuxfr.org,2005:Diary/375432017-10-17T11:10:42+02:002017-10-17T11:10:42+02:00Pourquoi la recherche en langages de programmation ?Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li><a href="#pourquoi-la-recherche-en-langages-de-programmation">Pourquoi la recherche en langages de programmation ?</a></li>
</ul><p>Je fais de la recherche en langages de programmation. Dans le journal ci-dessus, j'explique pourquoi et comment, en essayant d'être accessible pour des gens qui connaissent peu (ou mal) la programmation et/ou la recherche.</p>
<h2 id="pourquoi-la-recherche-en-langages-de-programmation">Pourquoi la recherche en langages de programmation ?</h2>
<p>Les programmeurs et programmeuses ont inventé de nombreuses représentations symboliques des programmes qui sont exécutés par un ordinateur, représentations que l'on appelle <em>langages</em> de programmation. On peut les voir comme des langages utilisés pour parler avec l'ordinateur, un programme étant un texte dans ce langage, le code source. Mais il est important de se souvenir que la programmation est aussi une activité sociale: la plupart des programmes sont écrits par plusieurs personnes travaillant ensemble, et les programmes écrits par une personne seule sont souvent réutilisés, inspectés et modifiés par d'autres. Un programme transmet une intention à l'ordinateur, mais il la communique aussi à des humains.</p>
<p>Quand on programme, on est facilement irrité par les défauts du langage de programmation qu'on utilise; il est très difficile de concevoir un <em>bon</em> langage de programmation. On lui demande au moins les trois qualités suivantes :</p>
<ul>
<li>
<p>la <em>concision</em>: Les tâches simples doivent être décrites par des programmes simples, pas par des programmes gros ou complexes. Les tâches complexes nécessitent des programmes complexes, mais la complexité du programme doit venir uniquement du domaine métier (les spécificités de la tâche requise), sans complexité incidente imposée par le langage de programmation.</p>
<p>Par exemple, les premières recherches en intelligence artificielle ont révélé le besoin d'un bon support, par le langage de programmation, du <em>backtracking</em> (retour en arrière) : annuler une série de décisions prises pour atteindre un certain but, en cas d'échec, pour commencer à nouveau selon une méthode différente. Certains langages de programmation rendent beaucoup plus facile d'exprimer cela que d'autres.</p>
</li>
<li>
<p>la <em>clarté</em>: En lisant le texte d'un programme, il faut qu'il soit facile de comprendre l'<em>intention</em> des personnes qui l'ont écrit. On dit qu'un programme a un <em>bug</em> (un défaut de fabrication) quand sa signification (pour l'ordinateur) ne correspond pas à l'intention de ses auteurs—une erreur a été faite pendant la transcription des idées dans le texte du programme. La clarté est un composant essentiel de la sûreté (éviter les comportements inattendus et dangereux). Pour l'améliorer, certaines constructions des langages de programmation nous aident à exprimer notre intention, et les concepteurs et conceptrices de langages de programmation travaillent à concevoir des outils pour vérifier automatiquement que l'intention ainsi exprimée est cohérente avec le reste du texte du programme.</p>
<p>Par exemple, l'un des pires problèmes de sécurité découvert en 2014 (le fait que tous les ordinateurs et téléphones Apple ne vérifiaient pas correctement l'authenticité des sites webs demandant une connection sécurisée) était causé par une ligne dans le texte d'un programme qui avait été dupliquée—écrite deux fois au lieu d'une seule. La différence entre l'intention du programmeur (vérifier l'authenticité des communications sécurisées) et le comportement réel du programme (permettant à des mauvais acteurs de se faire passer pour votre banque ou boîte email, intercepter vos paiement en ligne, etc.) était considérable, et pourtant ni les humains ni les outils automatiques qu'ils utilisaient n'avaient repéré cette erreur.</p>
</li>
<li><p>la <em>cohérence</em>: Un langage de programmation devrait avoir une structure très régulière, pour qu'il soit facile pour ses utilisateurs et utilisatrices de deviner comment utiliser les parties du langages qu'ils ne connaissent pas encore bien. En particuliar, la cohérence aide la clarté : retrouver l'intention derrière le texte du programme demande une bonne connaissance du langage, et plus le langage est cohérent, prévisible, plus faibles sont les risques de mécompréhension. C'est un cas particulier d'un principe de conception plus général, le principe de surprise minimale.</p></li>
</ul><p>Bien sûr, la liste (non exhaustive) ci-dessus n'est que l'opinion informelle d'une personne pratiquant la programmation (moi-même), et non pas une affirmation scientifique établie rigoureusement. La programmation est un domaine riche qui met en jeu de nombreuses activités, donc la <em>recherche</em> scientifique sur les langages de programmation peut être entreprise, et devrait être entreprise, depuis de nombreux angles différents. Entre autres, les mathématiques (la formalisation), l'ingénérie, le design, les interfaces homme-machine, l'ergonomie, la psychologique, la linguistique, les neurosciences, la sociologie, et les personnes qui pratiquent la programmation ont toutes leur mot à dire sur comment concevoir de meilleurs langages de programmation.</p>
<p>Pour ma part, je travaille au sein d'une communauté scientifique qui utilise la formalisation mathématique comme son principal outil pour étudier, comprendre et améliorer les langages de programmation. Pour travailler sur un langage, on lui donne une sémantique formelle (ou plusieurs) en définissant les programmes comme des objets mathématiques, au même titre que les nombres ou les fonctions. La sémantique d'un langage est alors donnée par une relation (mathématique) entre les programmes et leur comportement. On peut ainsi prouver des théorèmes sur les langages de programmations eux-mêmes, ou sur les analyses et transformations de programmes.</p>
<p>Voir dans le détail comment la formalisation mathématique d'un langage de programmation peut guider sa conception est absolument fascinant—c'est une approche très abstraite d'une activité très concrète. Ma communauté de recherche a défini un certain nombre de propriétés qui peuvent s'appliquer ou non à la formalisation mathématique d'un langage donné (l'objet mathématique que l'on a défini pour représenter le langage), et qui capturent certains aspects de l'utilisabilité du langage. Il s'agit en quelque sorte d'un ensemble de <em>tests</em> pour évaluer un langage. Cet ensemble de tests évolue au fil du temps, car nous affinons notre compréhension de ces propriétés formelles et nous en proposons de nouvelles, à partir de nos expériences d'utilisation des langages existants ou expérimentaux.</p>
<p>Avoir une sémantique formelle d'un langage que l'on étudie est une façon de comprendre ce que les programmes de ce langage veulent dire, ce qui est une première étape nécessaire pour évaluer ou améliorer la clarté du langage—un programme ne peut pas être clair si on ne commence pas par se mettre d'accord sur ce qu'il veut dire. Construire cette formalisation est un travail difficile (technique) et chronophage, mais son pouvoir de simplification ne peut pas être surestimé. Le travail de formalisation agit comme une loupe qui grossit les irrégularités, et suggère naturellement des changements du langage qui peuvent améliorer drastiquement sa cohérence. Il nous encourage à construire (ou reconstruire) le langage autour d'un petit ensemble de concepts centraux et indépendants, ses briques de base—c'est la meilleure façon de rendre la formalisation plus facile. Il peut donc améliorer aussi la concision, puisque des concepts avancés peuvent être décrits de façon simple en combinant ces briques de base. Bien sûr, trouver les <em>bonnes</em> briques de base demande une connaissance du domaine métier (celui des programmes dont on veut améliorer l'écriture dans ce langage); pour avoir des idées vraiment nouvelles il faut souvent explorer avec des prototypes ou faire des études d'usage, en dehors de l'activité de formalisation. La méthode de conception de langages que je préfère, c'est donc la co-évolution d'un langage et de sa formalisation, les activités de formalisation et de programmation ayant lieu en même temps, pour informer et diriger le processus de conception.</p><div><a href="https://linuxfr.org/users/bluestorm/journaux/pourquoi-la-recherche-en-langages-de-programmation.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/112896/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/bluestorm/journaux/pourquoi-la-recherche-en-langages-de-programmation#comments">ouvrir dans le navigateur</a>
</p>
gaschehttps://linuxfr.org/nodes/112896/comments.atom