Voir les cours et résoudre les problèmes en :
Le C est un langage de programmation impératif conçu pour la programmation système. Inventé au début des années 1970 avec UNIX, C est devenu un des langages les plus utilisés. De nombreux langages plus modernes se sont inspirés de sa syntaxe. Il privilégie la performance sur la simplicité de la syntaxe. [En savoir plus]
Le C++ est un langage de programmation impératif. Inventé au début des années 1980, il apporte de nouveaux concepts au langage C (les objets, la généricité), le modernise et lui ajoute de nombreuses bibliothèques. C++ est devenu l'un des langages les plus utilisés. Sa performance et sa richesse en font le langage de prédilection pour les concours. [En savoir plus]
Pascal est un langage de programmation impératif inventé dans les années 1970 dans un but d'enseignement. Quoiqu'encore utilisé à cette fin, l'absence de bibliothèque standard en limite son utilisation malgré une grande efficacité. Sa syntaxe a été reprise par d'autres langages plus modernes avec plus ou moins de succès. [En savoir plus]


Remarque : Les cours pour ce langage ne sont disponibles que jusqu'au chapitre 4, « Lecture de l'entrée ». Les corrections sont toutefois toujours fournies.
OCaml est un langage de programmation fonctionnel inventé au milieu des années 1990. Il permet aussi une programmation impérative ou objet. Il permet d'écrire des programmes courts et faciles à vérifier et est ainsi utilisé pour certains systèmes embarqués très sensibles comme ceux des avions. Il est utilisé dans l'enseignement en classes préparatoires aux grandes écoles. [En savoir plus]


Remarque : Les cours pour ce langage ne sont disponibles que jusqu'au chapitre 4, « Lecture de l'entrée ». Les corrections sont toutefois toujours fournies.
Java est un langage de programmation impératif et orienté objet. Inventé au début des années 1990, il reprend en grande partie la syntaxe du langage C++ tout en la simplifiant, au prix d'une performance un peu moins bonne. S'exécutant dans une machine virtuelle, il assure une grande portabilité et ses très nombreuses bibliothèques en font un langage très utilisé. On lui reproche toutefois la « verbosité » de son code. [En savoir plus]


Remarque : Pour un débutant souhaitant apprendre Java, nous conseillons fortement de commencer par JavaScool, plus facile à apprendre, bien que fortement similaire.
Java's Cool (alias JavaScool) est conçu spécifiquement pour l'apprentissage des bases de la programmation. Il reprend en grande partie la syntaxe de Java sur laquelle il s'appuie, mais la simplifie pour un apprentissage plus aisé. La plateforme JavaScool est accompagnée d'un ensemble d'activités diverses de découverte de la programmation. [En savoir plus]
Python est un langage de programmation impératif inventé à la fin des années 1980. Il permet une programmation orientée objet et admet une syntaxe concise et claire qui en font un langage très bien adapté aux débutants. Étant un langage interprété, il n'est cependant pas aussi performant que d'autres langages. [En savoir plus]
Plans de robots

On a expliqué les fonctions en prenant l'images de robots. Rappelons le principe : lorsque le robot est appelé, il ramasse les objets qui sont posés devant lui, il effectue des actions, puis il dépose éventuellement un objet avant de partir. On pourrait croire que pour chaque fonction, on a un robot qui dort dans un coin, et qu'à chaque fois que la fonction est appelée, on réveil le robot pour qu'il fasse son travail. Eh bien ce n'est pas tout à fait comme cela que ça se passe.

En fait, une fonction, c'est un manuel de fabrication pour un robot. Au début, aucun robot n'est présent. Les robots sont fabriqués dès qu'on a besoin d'eux, et jetés à la poubelle dès qu'on en a plus besoin. La fonction que le programmeur écrit correspond aux plans de constructions du robot. En d'autres termes, lorsqu'on appelle une fonction, un robot est construit, ce robot fait son travail, puis il est détruit. Ce n'est pas très écologique de gaspiller autant de robots, mais comme tout ce qu'on fait est entièrement virtuel, aucune pollution n'est engendrée.

Pour faire son travail, un robot peut faire appel à d'autres robots. Par exemple, la fonction suivant affiche successivement ses deux paramètres qui sont de type int :

let print_2_int x y =
  print_int x;
  print_int y;
  in

Supposons que l'on écrive maintenant print_2_int 9 5. Détaillons ce qui se passe :

  1. Un robot A est créé selon le modèle print_2_int. A est donc programmé pour ramasser deux objets et appeler print_int sur chacun d'entre eux.
  2. Le robot A est ensuite mis en route. Il ramasse le 9 et le 5.
  3. Ensuite, A appelle print_int 9. Pour cela, il pose le 9, et demande la construction d'un robot avec le plan de construction print_int.
    1. Un robot B est créé selon le modèle print_int.
    2. Le robot B ramasse l'entier 9, et l'affiche.
    3. Le robot B a fini son travail, il s'auto-détruit.
  4. Après, A appelle print_int 4. Pour cela, il pose le 4, et demande la construction d'un robot avec le plan de construction print_int.
    1. Un robot C est créé selon le modèle print_int.
    2. Le robot C ramasse l'entier 4, et l'affiche.
    3. Le robot C a fini son travail, il s'auto-détruit.
  5. Le robot A a fini son travail, il s'auto-détruit.

Il est important de noter qu'il n'y a aucune relation entre le robot B, qui affiche le 9, et le robot C, qui affiche le 4, si ce n'est qu'ils ont été fabriqué tous deux selon le même plan de fabrication, à savoir la fonction print_int.

Définition de récursif

Un robot peut donc appeler d'autres robots. Dans l'exemple qui précède, un robot programmé selon la fonction print_2_int appelait des robots programmés selon la fonction print_int.

Maintenant, il est possible qu'un robot, pour effectuer sont travail, fasse appel à un autre robot qui soit programmé de la même manière. Traduit en termes de fonctions, cela donne :

Une fonction récursive est une fonction qui s'appelle elle-même.

Voyons tout de suite un exemple. On va fabriquer un robot qui ramasse un entier n, et qui va calculer la valeur de la factorielle de n, c'est on le rappelle le produit des n premiers entiers. On sait déjà coder ça avec des boucles for ou while, mais cette fois on va faire sans. Pour cela, on va partir du principe que le produit des entiers compris entre 1 et n est égal à n fois le produit des entiers compris entre 1 et n-1.

Pour calculer factorielle de n, notre robot va donc procéder en deux étapes. D'abord il va faire appel à un robot assistant (un robot distinct, mais programmé pareil) pour calculer factorielle de (n - 1). Ensuite il va multiplier le résultat obtenu par n, et retourner le résultat.

Que fait le robot assistant pour calculer factorielle de (n - 1) ? Il fait la même chose :

il utilise encore un autre robot assistant, qui sera chargé de calculer la factorielle de (n - 2), puis il multiplie le résultat par (n - 1). Mais quand cela s'arrête-t-il ? Au bout

d'un moment, il faudra calculer la factorielle de 1. Pour cela, il n'y a pas besoin d'utiliser de robot assistant, car la valeur du résultat est trivial : c'est 1.

On peut maintenant écrire le plan de fabrication de notre robot, c'est-à-dire la fonction récursive factorielle :

let factorielle n =
  if n = 1
     then 1
     else n * (factorielle (n-1))
  in
  • La fonction prend un entier n en argument.
  • Si n vaut 1, alors on retourne 1.
  • Sinon, on retourne n fois la factorielle de n - 1.

Si on rajoute une comme print_int (factorielle 5) et qu'on essaie de compiler, on obtient un message d'erreur :

File "test.ml", line 4, characters 16-27:
Unbound value factorielle

L'erreur se situe au niveau du nom factorielle qui se situe dans le corps de la fonction factorielle. Cette erreur est normale : on est en train de définir la fonction factorielle, donc elle n'est pas encore définie. Pour résoudre ce problème, il suffit de rajouter le mot clé rec juste après le let. Il permet d'indiquer que l'on définit une fonction récursive. Maintenant :

let rec factorielle n =
  if n = 1
     then 1
     else n * (factorielle (n-1))
  in

print_int (factorielle 5);

le code compile et s'exécute correctement, affichant le résultat 120.

Pour définir une fonction récursive, on place le mot clé rec entre le let et le nom de la fonction.

On peut suivre l'ordre d'appel des fonctions en ajoutant un print_int n tout au début du corps de la fonction. Ainsi :

let rec factorielle n =
  print_int n;
  print_string " ";
  if n = 1
     then 1
     else n * (factorielle (n-1))
  in

print_int (factorielle 5);
affiche 5 4 3 2 1 120.
Pensez à vous inscrire pour valider les cours et résoudre les exercices.