Author: Christian.Queinnec@lip6.fr

## Introduction

Les langages de programmation fonctionnelle et de programmation impérative s'opposent principalement sur le contrôle de l'exécution des programmes et la gestion mémoire des données.

- un programme fonctionnel calcule une expression. Ce calcul donne lieu à la production d'une valeur. L'ordre dans lequel les opérations nécessaires à ce calcul sont effectuées et la représentation physique des données manipulées sont indifférents puisque le résultat est identique dans tous les cas. Dans un tel cadre, la récupération de la mémoire est gérée implicitement par le langage : on fait appel à un récupérateur automatique de mémoire ou GC1.
- un programme impératif est une suite d'instructions modifiant un état mémoire. Chaque étape de l'exécution est encadrée par des structures de contrôle rigides indiquant la prochaine instruction à exécuter. Les programmes impératifs manipulent plus souvent des pointeurs ou des références sur des valeurs que les valeurs elles-mêmes. Il faut alors allouer et récupérer explicitement l'espace mémoire nécessaire au stockage des valeurs. Cela entraîne parfois des erreurs d'accès mémoire. Rien n'empêche néanmoins d'utiliser un GC.

Les langages impératifs fournissent un plus grand contrôle de l'exécution et de la représentation mémoire des données. Étant plus proche de la machine réelle, le code peut être plus efficace mais perdre en sûreté d'exécution. La programmation fonctionnelle, parce qu'elle offre un plus haut niveau d'abstraction, procure un meilleur niveau de sûreté d'exécution : le typage (dynamique ou statique) peut y être renforcé, évitant ainsi des opérations sur des valeurs incohérentes ; la récupération automatique de mémoire, quitte à perdre en efficacité, assure l'existence effective des valeurs manipulées.
Historiquement, ces deux paradigmes de programmation se sont vus consignés dans des univers distincts : les applications symboliques pour le premier, et numériques pour le second. Mais certaines choses ont évolué, en particulier les techniques de compilation des langages fonctionnels et l'efficacité des GC. D'autre part, la sûreté d'exécution est devenue un critère important, voire prépondérant, pour la qualité d'une application. En atteste << l'argument de vente >> du langage Java selon lequel l'efficacité ne doit pas prendre le pas sur la sûreté, tout en restant raisonnablement bonne. Et c'est une idée qui progresse dans le monde des producteurs de logiciel.
Objective CAML se situe dans cette lignée. Il marie les deux paradigmes de programmation permettant ainsi d'accroître son domaine d'application en facilitant l'écriture d'algorithmes dans un style ou dans l'autre. Il conserve néanmoins de bonnes propriétés de sûreté d'exécution grâce à son typage statique, son GC et son mécanisme d'exception. Les exceptions sont une première structure de contrôle d'exécution explicite; elles permettent d'effectuer une rupture/reprise de calcul. Ce trait est à la frontière de ces deux modèles car bien qu'il ne change pas le résultat d'un calcul, il peut modifier l'ordre d'exécution. Le fait d'introduire des données physiquement modifiables peut changer le comportement de la partie purement fonctionnelle du langage. En effet l'ordre d'évaluation des arguments d'une fonction devient déterminant si cette évaluation effectue des effets de bord. Pour cette raison, de tels langages sont dits << langages fonctionnels impurs >>. On perd en effet en niveau d'abstraction car le programmeur doit tenir compte du modèle mémoire ainsi que du déroulement du programme. Cela n'est pas toujours négatif, en particulier pour l'efficacité du code écrit. Par contre, les traits impératifs modifient le système de types du langage : certains programmes fonctionnels, correctement typés d'un point de vue théorique, ne le sont pas en pratique du fait de l'introduction des références. Néanmoins, de tels programmes pourront se réécrire facilement.