jeudi 14 mai 2009

Lua

Le bricoleur pur et dur a toujours son couteau suisse dans la poche; le programmeur pur et dur a toujours son langage favori sous la main.

Ce genre de langage-couteau-suisse se distingue par certaines caractéristiques:
* la gestion de la mémoire y est automatique,
* c'est un langage interprété,
* de nombreuses librairies sont disponibles,
* sa syntaxe est simple,

C'est un langage avant tout pragmatique: les créateurs ne recherchent pas la pureté absolue (pur objet ou pur fonctionnel), ou la performance absolue, mais plutôt une ergonomie optimale. Oui, l'ergonomie ne s'applique pas seulement aux postes de travail, aux appareils electro-ménagers ou aux gadgets électroniques.

Pour ma part, je recherche une qualité supplémentaire: que le langage soit tout-terrain. Il doit fonctionner aussi bien sous Linux que Windows, mais aussi sur les systèmes embarqués tels que ceux sur lesquels je travaille (à base de processeurs 32bits tournant à100-200MHz, disposant de seulement quelques Mo de RAM et faisant tourner un système Linux léger).

Cela impose indirectement certaines contraintes de performance. Cela met en fait hors course la plupart des candidats, à commencer par Python, Ruby et TCL. En fait, il ne reste quasiment que Lua, qui est le seul langage interprété à concurrencer Forth en matière de performances. Il est certes nettement plus gros que lui, mais il n'y a guère qu'un autre système Forth pour concurrencer Forth sur ce point. En contrepartie, Lua offre la gestion de mémoire automatique et une syntaxe plus naturelle.

En fait, Lua est assez proche du langage "orienté utilisateur" que je cherche à créer. Pour commencer, il a toute ma reconnaissance pour ne pas être encore un de ces langages orientés objet. Il est difficile d'en trouver un qui ne l'est pas ces temps-ci, comme si cela était une condition sine qua non. Le seul pas en direction de l'orienté-objet est une facilité de syntaxe dont l'utilité se justifie d'elle-même: si elle s'avère pratique pour le programme que vous écrivez, c'est que le style orienté-objet est certainement le plus adapté. Si vous ne savez que penser en termes d'orienté-objet, et bien, vous devriez envisager de vous faire trépaner, mais vous pouvez construire un système de classes etc, ou adopter l'un de ceux créé par d'autres.

Ensuite, l'attention qui a été prêtée à la facilité d'intégration des librairies C avec le language. C'est un point important parce que ce type d'intégration est parfois difficile car s'y cumulent les défauts de la librairie et du langage-hôte. Lua simplifie les choses dans ce domaine en présentant une interface compréhensible et compacte. Cela incite à faire ces intégrations, et plus de librairies intégrées signifie plus de fonctionnalités disponibles pour le langage. C'est l'une des clefs du succès de Python.
A cela il faut ajouter que Lua donne le choix entre une intégration par librairie dynamique ou statique de manière transparente. L'un permet que l'interpréteur garde une taille raisonnable, et l'autre peut être plus pratique, plus compact, mais aussi permet le fonctionnement sur des plateformes qui ne savent pas gérer les librairies dynamiques.

Enfin, Lua est doté d'un ensemble équilibré et efficace de caractéristiques: clôtures, syntaxe avec juste ce qu'il faut de facilités, coroutines, et les metatables.


Lorsque j'ai commencé à avoir une idée claire du langage que je voulais, j'ai fait quelques recherches: l'expérience laisse à penser que tout ce que vous pouvez imaginer en matière de logiciel existe quelque part sur la toile. Pour le coup, il ne s'agissait pas d'écrire un interpréteur simple comme Forth, car ce que je veux implique de l'analyse de syntaxe, de la gestion automatique de mémoire, et de la vérification de type. Mes recherches ont été infructueuses; Lua, que je connaissais déjà est ce qui s'en rapproche le plus.
Je suis en train d'implémenter très lentement l'interpréteur pour mon langage; la difficulté de cette implémentation est à la auteur de mes craintes. Pourtant, je continue cette implémentation plutôt que d'adopter Lua car celui-ci a, à mes yeux, des défauts importants.

Ceux qui connaissent Lua auront remarqué qu'une des différences d'avec ce que je souhaite est la vérification de types; Lua est un langage dynamiquement typé alors que je veux un langage fortement et statiquement typé, une différence qui reste aujourd'hui le sujet de guerres de clocher virulentes. L'un et l'autre ont leurs avantages et leurs inconvénients. La raison de ma préférence pour le typage statique tient probablement au fait que je suis, le jour, programmeur pour système embarqué, et que le typage statique constitue une barrière de plus contre les bogues.
Le typage dynamique de Lua, couplé avec son principe de fonctionnement basé sur les tables, amène un inconvénient majeur: une simple faute de frappe peut amener un disfonctionnement incompréhensible. C'est l'assurance de perdre bêtement de temps à autres une heure ou deux pour une simple faute de frappe. Cela peut être à la limite acceptable quand on est prévenu de ce problème; après tout, quiconque c'est fait "avoir" deux ou trois fois par un point-virgule mal placé ou un "break" manquant en C apprend à être vigilant sur ces pièges.
Un autre problème chez Lua est la qualité des librairies. Un symptôme assez représentatif est l'usage à tort et à travers de chaines de caractères au lieu de codes numériques, notamment pour les codes d'erreur. On peut même le voir dans les fonctions intégrées du langage: la fonction type() renvoie la chaine "string", "table", etc. selon le type de l'argument passé. Outre le problème de la faute de frappe, c'est selon toute vraissemblance inefficace: si l'égalité peut être déduite efficacement en comparant les adresses des chaines (moyennant une optimisation de compilation que Lua fait certainement, sans quoi cela devient franchement stupide), si les adresses sont différentes le système doit en passer par une comparaison du contenu des chaînes (direct ou indirect - en tout cas c'est moins efficace que de comparer deux entiers).
Dans les librairies qui sont des contributions externes, j'ai vu tantôt des fonctions qui retournaient des chaines en guise d'erreur, tantôt un message d'erreur et un code d'erreur. Dans un autre registre, dans une autre librairie on peut voir un usage arbitraire des" metatables"; par arbitraire j' entend que cet usage n'est en rien justifié ou justifiable. Pour terminer, il faut noter que ce n'est que récemment que Lua c'est inspiré de Python, et offre une distribution incluant un éventail relativement convainquant de librairies (où j'ai d'ailleurs vu ces problèmes).
Globalement, le problème est que les auteurs de Lua semblent ne s'occuper que du langage et se désinteresser de la qualité des librairies. Or, cette qualité égale en importance les caractéristiques propres du langage. Il faudrait pour Lua que quelqu'un (ou un groupe) s'occupe de définir les règles de bonne conception des interfaces pour les librairies, évalue la qualité de leur implémentation et de leur documentation, choisisse entre plusieurs librairies qui offrent les mêmes fonctionnalités. On peut trouver quelque chose qui va dans ce sens sur le Wiki de Lua, mais cela reste très embryonnaire.
Pour conclure, il faut qu'une entité régisse les librairies. "Regir" a pour racine latine rex ("roi"). Sur d'autres projets Open Source, on se plaint parfois du caractère autoritaire de l'équipe de développement en charge du projet, car elle refuse tel ajout ou telle modification. Mais je pense que l'inverse, une équipe beni oui-oui qui fait ce qui suggéré sans discernement, est bien pire.

Aucun commentaire:

Enregistrer un commentaire