Mythe : Lisp est un langage interprété

Nous avons trouvé deux définitions possibles de langage interprété :

  1. langage qui doit forcément être implémenté sous forme d'interpréteur, ou
  2. langage possible à implémenter sous forme d'interpréteur.

Si nous choisissons la première définition, alors aucun langage n'est interprété. Si par contre nous choisissons la deuxième définition, alors tous les langages sont interprétés. On constate alors qu'il s'agit d'une caractérisation non pas du langage mais de son implémentation.

On peut bien sûr se poser la question sur la façon habituelle d'implémenter le langage, mais c'est une question délicate. Prenons un langage comme Scheme, similaire dans son apparence à Lisp. Il est tellement facile d'écrire un interpréteur Scheme que beaucoup d'étudiants en informatique ont fait cet exercice. Il y a donc un grand nombre d'implémentations de Scheme sous forme d'interprète. Pourtant, ce n'est pas la bonne façon d'implémenter Scheme, mais simplement la plus facile. Toutes les implémentations professionnelles de Scheme sont compilées. Est-ce que cela veut dire que Scheme est un langage interprété?

De fait, il y a souvent confusion entre interprétation et interactivité (ou plutôt incrémentalité). Certains pensent à tort qu'une implémentation compilée implique que le programme doive être intégralement compilé (et ``linké'') avant exécution du programme principal (voir section 2.3) et par conséquent, qu'un environnement interactif et incrémental soit forcément interprété. Ils ignorent la technique de la compilation incrémentale qui permet de compiler une seule fonction à la fois voire une seule expression à la fois. Il est donc faux que incrémentalité implique interprétation donc lenteur. Il est donc faux que Lisp est lent.

Le système CMUCL utilisé dans ce livre contient en fait un interpréteur et un compilateur (en fait deux). L'interpréteur est responsable de l'évaluation d'expressions tapées interactivement à partir de la boucle REPL. Le compilateur peut être utilisé grâce à un appel explicite soit sur une seule fonction, soit sur un fichier entier. En pratique, Emacs permet d'appeler le compilateur sur toute fonction qui a été modifiée et de la charger dans l'environnement de programmation.

Irene DURAND
2011-10-14