blog2geek.com
LLBAvatar de LLB

38 billets | Profil

Recherche Google

ce blog tous
Derniers billets Connexion
Archives

test

12/07/2007

[Lang] Anubis

Avant-propos : j'essaie ici de mettre en évidence quelques problèmes du langage Anubis et de critiquer quelques choix. Malgré tout, je pense que c'est un langage intéressant et qu'il contient de bonnes choses.

Un petit billet sur ce langage français encore peu connu et peu utilisé. Il y a toutefois quelques entreprises qui l'utilisent (il y en a 3, de ce que j'ai lu), Anubis ne mérite donc pas d'être relégué au rang des langages ésotériques. Non, c'est un langage tout ce qu'il y a de plus sérieux. J'en ai entendu parler pour la première fois il y a 2 ans et je suis de temps en temps son évolution. J'avais testé le compilateur une fois, mais je ne l'ai jamais vraiment utilisé.

C'est un langage fonctionnel (on peut donc manipuler les fonctions comme n'importe quel autre type de données) basé sur la théorie des catégories bicartésiennes fermées. C'est un concept mathématique que je ne maitrise absolument pas, mais je voulais juste dire que le langage s'appuie sur de solides bases mathématiques. L'auteur est d'ailleurs avant tout un mathématicien. Il a placé la sûreté au centre du langage. Le compilateur Anubis est donc peu permissif : un code bogué ne compilera probablement pas (sauf erreur de logique...). De ce fait, le temps de débogage est quasiment réduit à 0. Cela fait donc penser à Caml, en plus "extrémiste".

Un petit mot sur la licence : on ne peut utiliser le compilateur qu'à des fins personnelles et non lucratives. Ou alors, il faut demander une autorisation aux auteurs. Je ne m'attarderai pas là-dessus, mais la licence peut être rédhibitoire pour beaucoup de personnes.

 

Pattern matching (filtrage)

Notion importante dans le langage, le système de filtrage d'Anubis est bien plus exigeant que ce que l'on trouve dans les autres langages. Le filtrage est nécessairement exhaustif (il couvre tous les cas) et non redondant (il n'y a donc pas d'ordre entre les différentes branches). Ces deux aspects améliorent grandement la sûreté du langage. L'exhaustivité (vérifiée à la compilation) garantit qu'il n'y aura en aucun cas d'erreur.

Seulement, à y regarder de plus près, on a l'impression que c'est le même mécanisme que dans OCaml, en enlevant tout ce qui est potentiellement dangereux. On réduit donc l'expressivité du langage, en ne faisant pas confiance au programmeur. En effet, dans OCaml, tout filtrage pouvant potentiellement ne pas couvrir tous les cas génère un warning (qu'il faut considérer comme erreur). Par ailleurs, lorsque l'on n'utilise pas d'expressions gardées (les "when" dans le "match") en Caml, ni de valeur constante dans le motif, on obtient exactement la même sûreté que dans Anubis.

Un programmeur rigoureux qui se limite volontairement fera exactement les mêmes choses en Caml et en Anubis. Seulement, en Caml, il n'y sera pas obligé. Et quand il est sûr de lui, quand il sait ce qu'il fait, il sera heureux de profiter des mécanismes d'OCaml, améliorant l'expressivité du langage.

 

Exceptions

Deuxième point important : les exceptions. Son concepteur se vante de ne pas avoir la notion d'exception en Anubis. Je suis d'accord avec lui : l'abus d'exceptions est très néfaste. Beaucoup de langages récents abusent des exceptions et des pointeurs nuls. Ce sont des fléaux qui détruisent souvent la sûreté des programmes. Seulement, je ne suis pas entièrement d'accord avec lui, il y a des cas où cela me semble utile. Si on réfléchit aux "erreurs" qui peuvent survenir dans un programme, on trouve entre autres : l'utilisation de pointeurs nuls (j'en ai déjà parlé : ça ne devrait jamais être utilisé et je ne comprends pas pourquoi on en trouve encore dans Java, .NET et la majorité des langages de script) ; la division par 0 ; le mauvais accès à un élément d'un tableau ; l'ouverture d'un fichier qui n'existe pas.

Les pointeurs nuls, je le répète : on peut s'en passer sans problème. C'est d'ailleurs le cas dans Caml, Haskell et d'autres langages. Ça ne manque en aucun cas.

La division par 0. Il est vrai qu'il est impossible de détecter cette erreur à la compilation (c'est possible dans certains cas, mais pas dans le cas général). Alors que certains langages préhistoriques plantent à l'exécution (C...), d'autres utilisent des exceptions (Java, Caml, C#...). Une exception, c'est un peu plus propre, puisqu'on a un beau message d'erreur, et l'on peut la rattraper si l'on sait ce que l'on fait. Anubis utilise un type distinct : Maybe(int) (équivalent au "int option" de Caml). Dans l'idée, c'est intéressant. Dans la pratique, cela risque d'être pénible. Imaginez : à chaque fois que vous effectuez une division, vous devez gérer le cas de la division par 0. Même quand vous êtes sûr de vous. Je n'ai pas testé, mais a priori, ça interdit de fait les expressions du type : a * (b / c). Le mauvais accès à un élément d'un tableau (ou d'une chaine de caractères). C'est un peu pareil. En général, on fait attention et l'erreur se produit très rarement. Dans le pire des cas, cela génère une exception. Dans Anubis, c'est différent : il faut systématiquement gérer le cas, comme pour la division.

Ouvrir un fichier qui n'existe pas ? Même solution dans Anubis. Il faut gérer le cas. Et cette fois, je trouve ça bien. C'est quelque chose qu'il faut gérer : renvoyer un type Maybe est une très bonne idée ici.

 

Au final, cela s'annonce assez lourd comme langage. Lourd, au nom de cette prétendue sûreté. Autant j'approuve le fait d'accorder de l'importance à la sûreté (un langage comme Java est très déficient sur ce point), autant je trouve ça exagéré dans Anubis. Il n'y a pas soi-disant de système d'exception. Et pourtant, je vois une faille.

Il existe dans Anubis une fonction "alert". Elle fonctionne comme un assert en C : elle provoque un arrêt brutal du programme. Cette fonction sert quand le programmeur est absolument sûr que le cas ne se produira pas. Une façon de dire au compilateur : "Tais-toi, je sais ce que je fais". Il devient donc possible de définir une fonction de division qui fait une division. En cas de division par 0, elle appelle "alert", sinon elle renvoie le résultat. Cela permet d'avoir un opérateur de division de type entier -> entier. On peut faire la même chose pour d'autres occasions. Finalement, on obtient la même chose qu'en Caml. On simule des exceptions... sauf qu'on ne peut pas les rattraper. Anubis me semble encore une fois être presque comme Caml, en moins expressif. Je considère que l'existence de "alert" est un aveu du concepteur : les exceptions sont parfois (rarement, mais parfois quand même) utiles.

 

Conclusion

Pour conclure, je pense que ce que l'on a dans Anubis, on peut l'avoir dans Caml, à condition de se restreindre et d'appliquer strictement une coding-style. Si, en Caml, on s'oblige à n'utiliser que du filtrage exhaustif et non redondant, si l'on s'oblige à typer explicitement toutes les valeurs, si l'on s'interdit l'utilisation d'exceptions, si l'on s'interdit les boucles... alors, je pense que l'intérêt d'Anubis par rapport à OCaml est vraiment très limité. Si l'on est paranoïaque (ce qui est possible pour une entreprise pour laquelle la notion de sûreté est vitale), il est même possible de redéfinir la bibliothèque standard de Caml pour supprimer les exceptions, redéfinir l'opérateur de division pour qu'il renvoie un "int option", etc. Par ailleurs, je ne suis pas convaincu que le niveau de maturité du compilateur Anubis égale celui d'OCaml. Ou plutôt : je suis convaincu qu'il ne l'égale pas.