Atención a todos los contenidos del sitio aún no está traducida al idioma 'Español'.
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]
Problématique

On veut écrire un programme qui demande n nombres à l'utilisateur, et en affiche la somme. Lorsque n est petit, on sait comment faire : lire tous les nombres avec des let, calculer alors la somme, et enfin afficher la valeur de cette somme. Mais si n est trop grand, on ne peut pas procéder ainsi. La solution consiste à ajouter successivement les valeurs données à un total, et d'afficher simplement le total à la fin :

soit total = 0;
faire n fois :
  demander un entier à l'utilisateur;
  ajouter cet entier au total;
;
afficher total;

Pour l'instant on n'est pas capable de coder ça. Pourquoi ?

Il n'est pas possible de modifier la valeur de total. Si on fait let total = 0 in au début du programme, total sera toujours associé à 0 dans la suite, et donc afficher total ne pourra afficher que 0.

On avait dit qu'on ne souhaitait pas que la valeur associée à un nom change. Ce souhait est toujours d'actualité, et on va arriver à résoudre le problème sans transgresser à cette règle. Voici comment.

On va simplement dire que total est le nom d'une boite. Du début, jusqu'à la fin. Ainsi le nom total reste toujours associé à la même valeur : cette valeur, c'est une boite. La subtilité, c'est qu'on va alors pouvoir changer le contenu de la boite. Le changer comme on veut, quand on veut, où on veut.

Réécrivons donc ce que l'on veut faire, en utilisant une boite, nommée total. Au début, on crée cette boite, et on met la valeur 0 dedans : 0 est le contenu initial de la boite. Ensuite, à chaque fois que l'utilisateur donne un nombre, on effectue l'opération suivante :

  • lire le contenu de la boite total,
  • faire la somme de cette valeur et de l'entier donné par l'utilisateur,
  • mettre cette somme dans la boite, à la place de ce qu'il y avait avant.

Version pseudo-code :

soit une nouvelle boite nommée total, avec 0 pour contenu
faire n fois :
  demander un entier à l'utilisateur;
  mettre dans la boite total : son contenu courant + l'entier donné;
;
afficher le contenu de la boite total;
Manipulations

Avant de spécifier la syntaxe permettant de manipuler les boites, nous allons faire deux remarques fondamentales.

1) Une boite est fabriquée pour contenir un certain type d'objets. Elle ne pourra en aucun cas contenir des objets d'un autre type. Ainsi, on distinguera les "boites à entiers" des "boites à réels", et des "boites à texte", qui sont des objets de natures distinctes (on dira plus tard de types distincts).

2) Une boite n'est jamais vide. Il faut toujours mettre un contenu dans une boite, même si ce contenu n'est pas intéressant. Ainsi, dès la création d'une boite, il faudra donner un contenu, dit "contenu initial".

Résumons :

Pour créer une boite, il faut donner un contenu initial. A tout instant, la boite contiendra un et un seul objet du même type que ce contenu initial.

Cette règle est relativement artificielle. L'objectif est surtout d'empêcher le programmeur de faire des erreurs. L'empêcher de mettre n'importe quel type de contenu dans n'importe quel boite, ou encore l'empêcher de demander le contenu d'une boite qui serait vide. L'intérêt est que si le programmeur se trompe, il sera prévenu au moment de la compilation, et il ne découvrira pas ce problème en utilisant son programme.

D'abord un petit point vocabulaire : techniquement parlant, on utilise le mot "référence" plutôt que "boite". De ce terme vient l'abréviation ref, qui va nous servir pour construire des références. Une boite conçue pour contenir des entiers sera donc appelée une "référence sur un entier". Par ailleurs, lorsqu'on change le contenu d'une référence, on dit que l'on "affecte" la nouvelle valeur à cette référence.

Voyons maintenant comment manipuler les références.

Pour créer une référence, on écrit le mot ref, suivi du contenu initial. Par exemple pour une référence contenant l'entier 15, on fait ref 15. Ensuite pour nommer cette référence, on utilise un let :

let b = ref 15 in

Pour obtenir le contenu d'une référence, on met un point d'exclamation devant son nom : !nom. Certaines personnes lisent le point d'exclamation : "bang", et ainsi !a se lit "bang a". Si on veut afficher le contenu de la boite précédente, on fait donc print_int !b. Ce qui donne au total :

let b = ref 15 in
print_int !b;

Remarque : il n'y a pas besoin de parenthèses autour de !b après le print_int, car l'opérateur ! est prioritaire.

Pour affecter un nouveau contenu à une référence, on écrit son nom, puis le symbole :=, et enfin son nouveau contenu. Changeons ainsi le contenu de b en le faisant passer de 15 à 18, et affichons ensuite la valeur du nouveau contenu :

let b = ref 15 in
print_int !b;
b := 18;
print_int !b;

Il est extrêmement important de comprendre le principe des références, car ces principes s'étendront par la suite à d'autres structures fondamentales.

Résumé des manipulations de références :

  • let nom = ref contenu in pour construire une nouvelle référence.
  • !nom pour accéder au contenu de la référence.
  • nom := nouveau_contenu pour affecter un nouveau contenu à la référence.
Erreurs

Le point d'exclamation sert à différencier le nom d'une boite de son contenu. Ainsi, b est une boite et !b est son contenu. L'oubli d'un point d'exclamation entraîne une erreur :

let b = ref 15 in
print_int b;
File "test.ml", line 2, characters 10-11:
This expression has type int ref but is here used with type int

Cette erreur est située sur le b après le print_int. Le compilateur nous dit que ce b a pour type "int ref", traduire "référence sur un entier". Mais on devrait avoir un "int", un entier, puisque print_int affiche des entiers.

L'oubli d'un ref :

let b = 15 in
b := 18;
print_int !b;
File "test.ml", line 2, characters 0-1:
This expression has type int but is here used with type 'a ref

L'erreur se situe sur le b de b := 18. Ce b est pour l'instant un entier, qu'on vient de poser égal à 15. Il est pourtant utilisé comme une 'a ref. Qu'est-ce que cela veut dire ? Simplement "référence sur quelque chose". Les 'a, 'b et autres lettres précédées d'un prime veulent dire "un type indéterminé".

On peut se demander pourquoi le compilateur n'a pas vu qu'on essayait de mettre 18 dans b, et pourquoi il n'a donc pas dit qu'on utilisait ici b comme int ref. La raison est la suivante : il ne s'est même pas donné la peine d'aller lire jusqu'au 18. Au moment où il a vu b := il signale déjà l'erreur, et s'arrête tout de suite après. En effet, l'opérateur d'affectation := doit obligatoirement être précédé du nom d'une référence.

Enfin l'écriture d'un simple signe = à la place d'un := provoque une erreur de type :

let b = ref 15 in
b = 18;
print_int !b;
File "test.ml", line 2, characters 4-6:
This expression has type int but is here used with type int ref

Souvenez-vous : la seule fois qu'on a utilisé un signe égal en dehors d'un let c'était pour réaliser un test d'égalité dans une structure if, du genre if x = 3 then .... Comme on le précisera plus tard, il est possible de réaliser des comparaisons aussi en dehors des structures if. C'est ce qui se passe ici : le compilateur pense que l'on essaie de tester si b et 18 sont égaux. Ce qui provoque un problème de type, vu que cela n'a pas de sens de regarder si une boite et un entier ont même valeur.

Pensez à vous inscrire pour valider les cours et résoudre les exercices.