Introduction à OCaml et Langages Fonctionnels
Introduction à OCaml et Langages Fonctionnels
CBS-N‟Djamena
Programmation Fonctionnelle
2022-2023
Dionlar lang
09/11/2022 programmation fonctionnelle 1
Plan
I-Généralités sur Programmation Fonctionnelle
• Historique
• Introduction
• Définition
• Analyse des paradigmes de programmation
• Concepts de la programmation fonctionnelle
• Quelques langages fonctionnels
II-Etude détaillée du cas de OCAML
Introduction à la programmation
09/11/2022 4
fonctionnelle
1-3 Définition
Introduction à la programmation
09/11/2022 5
fonctionnelle
1-4 Analyse des paradigmes de
programmation
• Emmanuel Saint-James classe les langages de programmation en trois
familles principales:
Programmation impérative
Le calcul s‟exprime par des modifications de l‟état de la machine. Parmi
les langages de programmation supportant essentiellement ce modèle,
citons Ada, Basic, C, Fortran, Pascal et bien d’autres.
Programmation applicative
Le calcul se réalise par la définition et l’application de fonctions.
Les langages de cette familles ont relativement récents (années80)
et assez peu connus .Citons ML, Haskell, Miranda.
Introduction à la programmation
09/11/2022 6
fonctionnelle
Analyse des paradigmes de programmation
Programmation déclarative
Le calcul se définit par l‟expression des propriétés du
résultat attendu. On peut placer dans cette catégorie aussi
bien Prolog que SQL, bien qu‟ils aient très peu de traits en
commun.
NB: Dans la pratique, les limites peuvent être floues;
certains langages vont emprunter des traits à plusieurs de
ces catégories. Il existe des langages fonctionnels “purs”,
tels Miranda ou Haskell, alors que d‟autres vont conserver
des aspects impératifs „‟impur‟‟ (ML).
Introduction à la programmation
09/11/2022 7
fonctionnelle
1-5 Concepts de la programmation fonctionnelle
Introduction à la programmation
09/11/2022 8
fonctionnelle
Concepts de la programmation fonctionnelle
Ils permettent de faire appel à l‟évaluation paresseuse, soit
explicitement, soit implicitement.
Introduction à la programmation
09/11/2022 9
fonctionnelle
1-6 Quelques langages fonctionnelles
Il est parfois difficile d'établir une frontière bien nette
entre langages fonctionnels et langages non fonctionnels,
parce que nombre de langages fonctionnels présentent des
traits qui ne le sont pas (c'est le cas de CAML par exemple),
et nombre de langages non fonctionnels possèdent des
aspects qui le sont.
Néanmoins, certains langages sont universellement
connus comme étant essentiellement des langages
fonctionnels.
Introduction à la programmation
09/11/2022 10
fonctionnelle
Quelques langages fonctionnelles(suite)
En voici quelques uns
Lisp(list processing), l'ancêtre de tous les langages
fonctionnels, créé en 1958 par John McCarthy. Très utilisé
en intelligence artificielle.
John McCarthy:
Il était au Massachusetts Institute of Technology (MIT). Il a publié
un article intitulé « Recursive Functions of Symbolic Expressions
and Their Computation by Machine, Part I .
Introduction à la programmation
09/11/2022 11
fonctionnelle
Quelques langages fonctionnelles(suite)
Common Lisp (en abrégé CL) est une spécification du
langage Lisp standardisée par l'ANSI.( American
National Standard Institute).
Scheme, dérivé de Lisp, créé dans les années 1970
au Massachusetts Institute of Technology (MIT) par Gerald
Jay Sussman et Guy L. Steele.
Le Lambda Calcul:
Il es difficil de parler de la programmation fonctionnelle
sans dire quelques mots du Lambda calcul,un travail
fondamental d‟Alonzo church,
Très fondamental pour les langages fonctionnels
Introduction à la programmation
09/11/2022 12
fonctionnelle
Quelques langages fonctionnelles(suite)
La famille des langages ML (Meta Language), issue des
travaux de Robin Milner de la fin des années 70, dont les
deux principaux représentants aujourd'hui sont SML
(Standard ML) et CAML(a été conçu à l'INRIA (Institut
National de Recherche en Informatique et
Automatique). (dans sa version OCAML).
Introduction à la programmation
09/11/2022 13
fonctionnelle
Quelques langages fonctionnelles(suite)
Haskell, langage fonctionnel pur. Créé en 1990. Une de
ses particularités est d'être un langage à évaluation
paresseuse (lazy).
• Le dernier standard est Haskell 2010
• il est fondé sur le lambda-calcul et la logique
combinatoire. Son nom vient du mathématicien et
logicien Haskell Brooks Curry.
Introduction à la programmation
09/11/2022 14
fonctionnelle
Quelques langages fonctionnelles(suite)
Iswim: If you see What I Mean
Introduit par Peter Landin en 1966;
Iswim est du Lambda calcul saupoudré du sucre
syntaxique;
Accepte l‟introduction de Let et Where ;
Autorise l‟utilisation de l‟indentation comme outil
syntaxique permettant d‟alleger l‟écriture des programmes;
APL: Acronyme de « A Programming Language »:
Concu par Kenneth Iverson en 1962 comme outil
mathématiques de description d‟algorithme
Introduction à la programmation
09/11/2022 15
fonctionnelle
Quelques langages fonctionnelles(suite)
Langage presque purement fonctionnel dans ses
concepts originales;
Les fonctions du langage opèrent globalement sur
les tableaux;
Les fonctions primitives sont représentées par les
caractères spéciaux;
Les opérateurs sont des fonctionnelles
Introduction à la programmation
09/11/2022 16
fonctionnelle
1-7 Conclusion
Nous avons fait un tour rapide des langages de programmation
fonctionnels:
D‟une part en traçant leur historiques;
D‟autre part en présentant leurs traits essentiels.
Certains langages applicatifs s‟industrialisent:
autrefois curiosité de laboratoires;
Aujourdhui,ils proposent de bonnes performances et des
environnements de programmation élaborés
Introduction à la programmation
09/11/2022 17
fonctionnelle
II-Programmation Ocaml
2-1 Introduction à Ocaml
Le langage de programmation fonctionnel choisi ici comme exemple,est
l‟Objectif CAML(OCAML).
Ce langage n‟étant pas un exemple parfait de la famille des langages
fonctionnels mais nous l‟avons choisi pour:
Sa simplicité;
son autonomie syntaxique;
ect….
2-2 Qu’est ce que programmer???
Le But de ce Cours est d‟apprendre à programmer, c‟est-à-dire:
Réussir à contrôler la machine;
Expliquer à la machine ce qu‟on veut qu‟elle fasse
Introduction à la programmation
09/11/2022 18
fonctionnelle
Qu‟est ce que programmer?(suite)
Malheureusement :
La machine n‟est pas intelligente;
Et elle ne comprend qu‟un langage extrêmement limité;
Alors difficile pour les humains d‟écrire dans ce langage machine.
Pour parler à la machine:
On va se faire assister par un traducteur;
capable de traduire un langage évolué, dit langage de programmation en
langage machine: appelé compilateur;
Le compilateur traduira du code Caml en code machine.
Il existe trois phases dans la production d‟un programme:
On écrit le code source du programme,c‟est-à-dire le texte en Caml (.ml);
On demande au compilateur de le traduire en code machine:c‟est la
compilation du programme;
Introduction à la programmation
09/11/2022 19
fonctionnelle
On demande à la machine d‟éffectuer le code machine :c‟est l‟exécution
du programme (.exe).
Exemple: Si on choisit d‟appeler « monsource.ml » le source et
« monprog.exe » l‟éxécutable,alors les trois phases de production du
programme seront:
• 2diter le fichier « monsource.ml » pour y écrire le code caml;
• effectuer la traduction par une commande "ocamlc -o monprog.exe
monsource.ml"ou par l‟icone « compiler »;
• exécuter le programme en tapant son nom "monprog.exe« ou cliquer sur
« éxécuter ».
2-3 Utilisation de Let , If , For
2-3-1 Instructions
2-3-1-1 Afficher du Texte
Pour afficher du texte , en Ocaml,on utilise la commande Print-string
"texte":
Print pour « Afficher » et
String pour « texte »
Introduction à la programmation
09/11/2022 20
fonctionnelle
Exemple: écrire un code Ocaml qui affiche « Bonjour le monde! ».
Code Ocaml:
Print-string " Bonjour le monde ! " ;
NB: Il est possible d’éffectuer plusieurs instructions de suite dans un
programme. Pour celà,il faut les écrire les unes après les autres séparées
par l’instruction Print-newline();
Exemple: Ecrire un code Ocaml qui affiche:
Bonjour tout le monde!
Au revoir!
2- 3-1-2 Afficher des nombres
Pour afficher un nombre entier, on utilise la commande print _int, se
traduisant littéralement affiche _entier.
Exemple: Essayer de prévoir ce que le code qui suit va afficher :
print_string " Voici dix - huit : ";
print_newline ();
print_int 18;
print_newline ();
Introduction à la programmation
09/11/2022 21
fonctionnelle
Autre exemple: Ecrivez maintenant un programme qui affiche d’abord l’entier
5, puis le texte "a pour carré", et ensuite l’entier 25.
Résolution:
print_int 5;
print_string "a pour carré ";
print_int 25;
Alors on obtient comme résultat après exécution:
5a pour carré25
NB: Ceci est du au fait que la fonction print _int n’affiche aucun espace avant
ou après l’entier. Pour obtenir un résultat satisfaisant, il faut donc rajouter des
espaces, avant et après le texte que l’on affiche avec print _string.
2-3-2 Déclaration
Considérons le programme suivant, qui affiche 5, puis le texte "a pour carré",
et enfin le carré de 5.Evitons d’afficher 25 mais le résultat 5 fois 5 en utilisant
les parenthèses.
Et en suite, changeons le chiffre 5 par 238,que se passera t-il dans le code??
Solution:Il suffit pour cela de remplacer 5 par 238.
Introduction à la programmation
09/11/2022 22
fonctionnelle
RQ: Si on voulait recommencer avec d’autres valeurs, on serait obligé de faire 3
remplacements à chaque fois, ce qui risque d’étre un petit peu pénible. On va donc
présenter un procédé permettant, un peu comme en mathématiques, de poser x la
valeur pour laquelle on veut effectuer les trois lignes de code précédentes. Une fois
la valeur de x posé, la lettre x désignera cette valeur.
2-3-2-1 Utilisation de Let
Syntaxe: let NomVariable = (... la valeur de la variable ...) in (... instructions
utilisant la Variable...)
Décryptage:
1. "let" se traduit "posons" ou encore "soit",
2. " NomVariable" est le nom de la vaiable que l’on est en train de poser,
3. le signe = indique qu’on va en préciser la valeur,
4. "in" se traduit "dans" ou " à l’intérieur de", (sous-entendu des instructions
suivantes).
5. il n’y a pas de point-virgule après le in.
Introduction à la programmation
09/11/2022 23
fonctionnelle
Example: Concrétisons cette théorie dans l’exemple précédent:
Le code peut s‟écrire:
let x = 238 in
print_int x;
print_string " a pour carré";
print_int (x * x);
Introduction à la programmation
09/11/2022 24
fonctionnelle
La requête d‟un nombre entier à l‟utilisateur se fait avec la commande read _int(),
traduction "lire un entier".
Syntaxe: Let NomVariable=read_int () in
Suite instructions
Exemple: Reprendre les exercices qui consistaient à afficher le nombre, à pour carré
et la valeur à calculer du carré en utilisant read_int().
Code:
let mon_nombre = read_int () in
print_int mon_nombre ;
print_string " a pour carré";
print_int ( mon_nombre * mon_nombre );
NB:Un read_ int() bloque l‟exécution du programme jusqu‟ à ce que l‟utilisateur
ait:
tapé un nombre entier et ;
appuyé sur la touche entrée du clavier.
A ce moment le mot read int() est remplacé par la valeur donnée.
Introduction à la programmation
09/11/2022 25
fonctionnelle
Application: Ecrivez un programme qui affiche le texte "Veuillez entrer un
nombre : ", qui demande ensuite un nombre entier à l’utilisateur, et qui
affiche alors sur la ligne suivante "Votre nombre est : ", suivi de la valeur du
nombre.
2-3-2-3 Lecture d’un texte
Pour demander à l’utilisateur une ligne de texte, on utilise la commande
read _line(), traduction "lire une ligne".
Syntaxe: Let texte = read_line () in
Suite instructions
Exemple: Ecrivez donc un programme qui affiche "Tapez votre texte : ", qui
demande alors un texte à l’utilisateur, puis qui affiche le texte fourni sur la
ligne suivante.
Code: print_string " Tapez votre texte : ";
let text = read_line () in
print_string text ;
Introduction à la programmation
09/11/2022 26
fonctionnelle
2-3-3 Les conditions
Nous allons voir une structure qui permet de déterminer le comportement
d’un programme en fonction du résultat d’un test.
Cette structure s‟appelle le If et il en existe trois types:
Le If simple;
Le If avec alternatif;
Le If avec multiple choix.
2-3-3-1 Le If simple:
Cette structure permet de déterminer le comportement d‟un programme en
fonction du résultat de test sans indiquer l‟action à réaliser au cas contraire.
Syntaxe: if (... la condition ...) then
(... bloc du then ...)
;
Exemple: Ecrire le programme qui demande à l‟utilisateur un entier et affiche
« le signe est positif ».
Introduction à la programmation
09/11/2022 27
fonctionnelle
let mon_nombre = read_int () in
if mon_nombre >= 0 then
print_string " le signe est positif ";
;
2-3-3-2 Le If avec alternatif: If,then,else
Cette structure permet de déterminer le comportement d‟un programme en
fonction du résultat de test en indiquant l‟action à réaliser au cas contraire.
Syntaxe: if (... la condition ...) then
(... bloc du then ...)
else
(... bloc du else ...)
;
Exemple: Reprendre l‟exercice précédent et en affichant « le signe est négatif »
au cas contraire. On considère zéro comme positif.
Introduction à la programmation
09/11/2022 28
fonctionnelle
let mon_nombre = read_int () in
if mon_nombre >= 0 then
print_string " le signe est positif ";
else
print_string " le signe est négatif ";
;
2-3-3-3 Le If avec multiple choix:
Cette structure permet de déterminer le comportement d‟un programme en
fonction du résultat de test en indiquant les différentes actions intermédiaires à
réaliser au cas contraire entre le If et le le Else.
Syntaxe: if (... la condition ...) then
(... bloc du then ...)
elseif (... la condition ...) then
(... bloc du elseif ...)
.
.
.
else
(... bloc du else...)
;
Introduction à la programmation
09/11/2022 29
fonctionnelle
Exemple: Reprendre l‟exercice précédent et en affichant « Nul » au cas où
l‟entier saisi est égal à zéro .
let mon_nombre = read_int () in
if mon_nombre > 0 then
print_string " le signe est positif ";
elseif mon_nombre = 0 then
print_string " Nul ";
else
print_string " le signe est négatif ";
;
Générale, les différents tests fonctionnent de la manière suivante:
• On teste la condition qui se trouve après le if.
• Si ce test est vérifié, on exécute juste le bloc du then.
• Dans le cas contraire, on exécute juste le bloc du elseif.
• Dans le cas contraire, on exécute juste le bloc du else.
• Dans les trois cas, on continue ensuite l‟exécution après le point-virgule
finale.
Introduction à la programmation
09/11/2022 30
fonctionnelle
Utilisation du if, then, else :
1. La condition peut s‟exprimer avec des comparaisons de valeurs : = pour
l‟égalité, <> pour la différence, < et > pour les comparaisons strictes, et <= et
>= pour les comparaisons larges.
2. Afin de délimiter les blocs, chacun d‟entre eux commence par begin et se
termine par end. Le code de chaque bloc doit, pour des raisons de lisibilité,
être indenté (d´écalé vers la droite).
3. La totalité de la structure if .. then .. else .. constitue une grosse instruction,
et il faut le terminer par un point-virgule.
Par exemple, on peut réécrire :
let mon_nombre = read_int () in
if mon_nombre >= 0 then
begin
print_string " positif ";
end
else
begin
print_string " négatif ";
end
;
Introduction à la programmation
09/11/2022 31
fonctionnelle
2-3-3-4 La Portée d’une déclaration
Les déclarations réalisées jusqu‟ à maintenant consistaient à associer un nom à
une valeur dans toute la suite du programme. Ce cas n‟est pas général : il arrive
qu‟un nom soit associé à une valeur uniquement durant un petit morceau du
programme. On dit alors que la "portée" de la déclaration est limitée.
2-3-4 Réduction des Blocs
Il s’agit d’alléger les notations dans les structures conditionnelles (avec if)
lorsque des blocs sont formés d’une seule instruction.
Exemple:
Begin Se résume juste en instruction
Instruction
End
2-3-5 Blocs vides, else implicite
Il s’agit cette fois d’alléger les notations dans les structures conditionnelles (avec
if) lorsque les blocs n’ont aucune instruction:
Un bloc vide begin end peut s‟écrire aussi comme un couple de parenthèses :
().
Introduction à la programmation
09/11/2022 32
fonctionnelle
Exemple:
let prenom = read_line () in
if prenom = " arthur " then
begin
print_string "c’est moi ";
print_newline ();
end
else
begin
end
;
Introduction à la programmation
09/11/2022 33
fonctionnelle
Se simplifie en :
let prenom = read_line () in
if prenom = " arthur " then
begin
print_string "c’est moi ";
print_newline ();
end
else
()
;
Dans une structure if, on peut se passer du "else ()".
let prenom = read_line () in
if prenom = " arthur " then
begin
print_string "c’est moi ";
print_newline ();
end
;
Introduction à la programmation
09/11/2022 34
fonctionnelle
Dans un tel cas, on peut, si on a envie placer le point-virgule après le end :
2-4 Répétitions
Un des avantages des programmes sur les humains est qu‟ils sont capables
d‟effectuer un traitement simple un très grand nombre de fois, rapidement et sans
fatiguer. Pour en profiter, il nous faut une structure permettant de répéter un
morceau de code un nombre de fois déterminé.
2-5 La boucle For
2-5-1 La boucle croissante
Syntaxe: for compteur = valeur_initiale to valeur_finale do
(... corps de la boucle for ...)
done ;
Le corps de la boucle consiste en une succession d‟instructions quelconques.
Le Fonctionnement de la boucle for, utilisée pour répéter un bloc :
1. Evaluer la valeur _initiale et la valeur _finale du compteur, ce sont les
bornes.
2. Prendre dans l’ordre croissant tous les entiers compris entre ces bornes,
incluses.
3. Pour chaque entier, copier le corps du for, et y déclarer le compteur égal à
cet entier..
Introduction à la programmation
09/11/2022 35
fonctionnelle
NB: avec valeur_initiale toujours plus petite que valeur_finale
Example: Ecrire le code ci-aprés en utilisant la boucle For:
print_string " bonjour ";
print_newline ();
print_string " bonjour ";
print_newline ();
print_string " bonjour ";
print_newline ();
Code demandé:
for i = 1 to 3 do
print_string " bonjour ";
print_newline ();
done ;
Introduction à la programmation
09/11/2022 36
fonctionnelle
RQ: Il peut arriver aussi ,comme dans les autres cas précédents,qu‟on demande à
l‟utilisateur de saisir le nombre fois que votre programme doit tourner.
Exemple: Ecrivez un programme qui demande `a l‟utilisateur le nombre de fois
que votre programme doit afficher "bonjour", suivi à chaque fois d‟un retour `a
la ligne.
let repete = read_int () in
for i = 1 to repete do
print_string " bonjour ";
print_newline ();
done ;
Les déclarations réalisées à l’intérieur du corps de la boucle ont une portée
limitée à ce corps.
Par exemple : for i = 1 to 3 do
let x = 8 in
print_int x;
done ;
Introduction à la programmation
09/11/2022 37
fonctionnelle
2-5-2 La boucle décroissante : Descente
Première possibilité: rester dans For croissant
On utilise dans ce cas à la partie print_int: nombre_final- compteur
Exemple: En utilisant une boucle for, écrivez un programme qui affiche tous les
entiers de 20 à 1 inclus, dans l‟ordre décroissant.
Deuxième possibilité: en utilisant Downto
Il existe une variante de la boucle for qui permet de faire la même chose plus
facilement. Pour cela, il suffit d‟utiliser downto `a la place de to. Traduction :
downto = en descendant jusqu‟à.
Exemple :Reprendre l‟exemple ci-dessus en utilisant Downto
for i = 20 downto 1 do
print_int i;
print_newline ();
done ;
Introduction à la programmation
09/11/2022 38
fonctionnelle
2-5-3 Cas particulier: Itérer un bloc
Répéter exactement la même chose ne sert en fait pas très souvent. On a plutôt
besoin de répéter presque la même chose, mais pour un paramètre différent `a
chaque fois. En voici un exemple.
print_int 5;
print_newline ();
print_int 6;
print_newline ();
print_int 7;
Exemple: Ecrire l‟exemple précédent en utilisant la boucle for.
for i = 5 to 7 do
print_int i;
print_newline ();
done ;
Introduction à la programmation
09/11/2022 39
fonctionnelle
3.Float,Int,Ref
3-1 Réels
3-1-1 Opérations
Pour l‟instant on n‟a utilisé que des nombres entiers. On a vu comment :
les lire avec read _int(),
les afficher avec print _int(),
et faire des opérations de bases dessus :
addition +,
soustraction -,
et multiplication *.
NB: Notez que la division de deux entiers n‟étant pas toujours un entier, le
symbole / prendra un sens différent de la division usuelle, comme on
l‟expliquera dans la prochaine section.
Introduction à la programmation
09/11/2022 40
fonctionnelle
Pour désigner la façon dont un ordinateur manipule les nombres réels, on utilise
l‟expression de "nombres flottants", "float" en anglais. En français les réels ont des
virgules, mais en anglais il y a un point.
Ainsi 4.56 vaut quatre virgule cinquante-six. Même si le nombre n‟a pas de
chiffres après la virgule, pour qu‟il soit considéré comme un float, il faut le faire
suivre d‟un point.
Exemple: 4. est un réel, alors que 4 est toujours un entier.
Pour les nombres négatifs, il suffit de mettre un moins devant : -234.81 par
exemple.
Enfin il est possible d‟utiliser la notation scientifique : 1.27e12 signifie 1.27*
1012.
A chaque opération sur les entiers, il va correspondre l‟analogue pour les floats.
On les lira avec read _float(), de la méme manière qu‟avec read _int(). La fonction
read float() est d‟ailleurs capable de lire un réel méme s‟il est donné par
l‟utilisateur sous la forme d‟un entier, comme par exemple 4 sans point à la fin.
Pour afficher des float, on utilisera print _float suivi de la valeur du réel.
RQ: Pour les opérations, il faut faire très attention car les symboles sont tous
suivis d‟un point.
Introduction à la programmation
09/11/2022 41
fonctionnelle
Cela traduit différentes méthodes de calculs entres les entiers et les réels. Par
exemple, une addition de deux réels n‟est pas réalisée par un ordinateur de la
méme maniére que l‟addition de deux entiers. On a donc:
l’addition +.;
la soustraction -. ;
La multiplication *. et enfin;
la division /.
Exemple: Ecrire un programme qui demande à l‟utilisateur un réel, qui affiche
d‟une part le produit de ce nombre par 3.4, et d‟autre part la valeur de
l‟opposé de ce nombre.
Code:
let x = read_float () in
print_float (3.4 *. x);
print_newline ();
print_float (-. x);
Introduction à la programmation
09/11/2022 42
fonctionnelle
Remarque : print_ float (-x) ne marche pas, car le - permet d‟opposer des
entiers, et pas des réels.
Il ne faut jamais diviser par zéro. Tout simplement parce qu‟on ne peut pas
prévoir le résultat.
Lorsqu‟on effectue une division par zéro en calculant sur des réels, un code
spécial est utilisé pour désigner le résultat.
Sous Windows :
• 1.#INF et -1.#INF respectivement pour plus et moins l‟infini.
• 1.#IND et -1.#IND pour des valeurs indéterminées.
Sous linux :
• inf. et -inf. respectivement pour plus et moins l‟infini.
• nan. et -nan. pour des valeurs indéterminées.
Exemple de code faisant apparaitre ces valeurs.
Introduction à la programmation
09/11/2022 43
fonctionnelle
print_float (5. /. 0.) ;
print_newline ();
print_float ( -1. /. 0.) ;
print_newline ();
print_float (0. *. ( 5. /. 0.) );
Sous Windows :
1.# INF
-1.# INF
-1.# IND
Et sous Linux :
inf .
-inf.
nan .
Application: Ecrire un programme qui demande deux réels et qui affiche le
carré de leur somme.
Introduction à la programmation
09/11/2022 44
fonctionnelle
Voilà ce qu‟il ne faut pas faire :
let x = read_float () in
let y = read_float () in
print_float ( (x +. y) *. (x +. y) );
NB: Le problème dans ce code est qu‟on répète deux fois le méme code, à
savoir (x +. y). Afin d‟éviter cela, il faut mieux poser la valeur de cette
somme avant, et d‟en faire le produit après.
let x = read_float () in
let y = read_float () in
let s = x +. y in
print_float (s *. s);
3-1-2 Valeur absolue, puissances
Pour calculer la valeur absolue d‟un réel x:
Syntaxe: abs _float x
Introduction à la programmation
09/11/2022 45
fonctionnelle
Example:
let x = read_float () in
print_float ( abs_float x);
NB: Si le paramètre de la fonction est le résultat d‟un calcul, il faut le mettre
entre parenthèses.
Exemple: Ecrire un programme pour prendre la valeur absolue d‟une
différence de deux réels saisis par l‟utilisateur .
Code :
let x = read_float () in
let y = read_float () in
let r = abs_float (x -. y) in
print_float r;
Pour prendre la racine carrée d‟un nombre réel x:
Syntaxe: sqrt x
Mais attention, la racine carrée d‟un nombre négatif n‟étant pas définie, on
risque une forme indéterminée. En fournissant le nombre -2.3 par exemple au
code suivant :
Introduction à la programmation
09/11/2022 46
fonctionnelle
let x = read_float () in
print_float ( sqrt x);
le programme affichera : -1.#IND.
Pour élever un nombre à une puissance:
Syntaxe: on utilise le symbole **
deux signes fois cote à cote,
qui se place entre le nombre et sa puissance.
Il faut faire attention au fait que ces deux valeurs sont des nombres réels tous
les deux.
Ainsi pour mettre un nombre x au cube, il faudra faire x ** 3.0 :
let x = read_float () in
print_float (x ** 3.0) ;
Introduction à la programmation
09/11/2022 47
fonctionnelle
3-1-3 Maximum, Minimum
La fonction max donne le plus grand de deux nombres réels. Il faut pour cela
placer les deux nombres après max, séparés par des espaces :
Exemple: print_float (max 4.5 8.6) ;
affiche donc 8.6.
La fonction min donne le plus petit de deux nombres réels, et s‟utilise
comme la fonction max.
Par exemple :
let x = read_float () in
let y = read_float () in
let r = min (x +. 5.) (y -. 5.) in
print_float r;
RQ: Erreur à éviter
Il faut faire attention à la priorité des opérateurs. Par exemple, si l‟objectif
du programme est de calculer la valeur absolue de la différence des nombres
2.3 et 3.4, alors le code suivant :
Introduction à la programmation
09/11/2022 48
fonctionnelle
print_float ( abs_float 2.3 -. 3.4) ;
Compile parfaitement, sauf qu‟il ne fait pas ce que l‟on veux.Il affiche: -1.1 et
non 1.1 comme attendu. Car les fonctions s’appliquent avant les opérations.
Conclusion : testez autant de situations différentes que possible pour vérifier
un programme.
Introduction à la programmation
09/11/2022 49
fonctionnelle
• cos pour le cosinus,
• acos pour la réciproque du cosinus : ("arccos" en français),
• cosh pour le cosinus hyperbolique ("ch" en français),
• acosh pour la réciproque du cosinus hyperbolique ("argch" en français).
3-2 Entiers
3-2-1 Division entiére et modulo
L‟opérateur / représente la division entière. C‟est-`a-dire qu‟il calcul le
quotient de deux entiers.
L‟opérateur mod (pour modulo) calcule le reste de la division entière.
Exemple: Supposons qu‟un fermier dispose de n œufs, et qu‟il souhaite
remplir des boites de 12. L‟expression (n / 12) donne le nombre de boites qu‟il
remplira entièrement. L‟expression (n mod 12) donne le nombre d‟oeufs qu‟il
trouvera dans la boite incomplète. En particulier, lorsque n est un multiple de
12, il n‟y a pas de boite incomplète, et dans ce cas (n mod 12) vaut 0.
Application: Ecrire un programme qui demande un entier à l‟utilisateur et
affiche pair ou impair selon les cas.
Introduction à la programmation
09/11/2022 50
fonctionnelle
Il s‟agit de tester si n est un multiple de 2, c‟est-à-dire si (n mod 2) vaut 0.
let n = read_int () in
if n mod 2 = 0
then print_string " pair « ;
else print_string " impair ";
Exemple: let x = 2 in
print_int x;
print_newline ();
let y = float_of_int x in
print_float y;
Application: Ecrivez une fonction qui demande deux entiers à l‟utilisateur, et
qui renvoie la valeur réelle de la division exacte du premier par le second.
Introduction à la programmation
09/11/2022 52
fonctionnelle
let x = read_int () in
let y = read_int () in
let divise = ( float_of_int x) /. ( float_of_int y) in
print_float divise ;
Pour convertir un réel en un entier, c‟est un peu plus délicat, car le réel ne
tombe par forcément pile sur un entier. On dispose de la fonction int _of_
float, traduction : "entier `a partir d‟un réel", qui se contente d‟effacer tous
les chiffres après la virgule du nombre réel.
Syntaxe: Int_of_float X
Ainsi :
int_of_float 4.2 = 4
int_of_float 4.9 = 4
int_of_float ( -4.2) = -4
int_of_float ( -4.9) = -4
RQ:
la fonction int _of_ float n‟est pas la fonction mathématique partie
entière. Cela `a cause de sa façon de traiter les nombres négatifs.
Introduction à la programmation
09/11/2022 53
fonctionnelle
Si vous avez besoin de calculer la vraie partie entière d‟un réelle x, faites :
(int_of_float (floor x)).
En bref, floor x représente le plus grand réel inférieur `a x qui n’ait que des
zéros après la virgule.
3-2-4 Limitation des int
Les nombres entiers ne peuvent pas être aussi grand ou aussi petit que l‟on
veut.
Un int est une valeur comprise entre -1073741824 et 1073741823.
CCL: Lorsqu‟on travaille avec des int, il faut faire attention à ne pas dépasser les
limites, car aucun message d‟erreur ne signale les dépassements.
3-3 Références
3-3-1 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
afficher simplement le total à la fin :
Introduction à la programmation
09/11/2022 54
fonctionnelle
soit total = 0;
faire n fois :
demander un entier `a 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.
Introduction à la programmation
09/11/2022 55
fonctionnelle
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 ;
Introduction à la programmation
09/11/2022 56
fonctionnelle
3-3-2 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".
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.
Introduction à la programmation
09/11/2022 57
fonctionnelle
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 `a cette
référence.
Syntaxe:
Pour créer une référence, on écrit le mot ref, suivi le 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 :
ref 15
let b = ref 15 in
let b = ref 15 in
print_int !b;
b := 18;
print_int !b;
Introduction à la programmation
09/11/2022 59
fonctionnelle
Application: Ecrivez un programme qui crée une boite nommée b contenant
10, puis qui augmente le contenu de cette boite de 5, et qui pour terminer
affiche le contenu de la boite (qui sera 15).
Contrainte : vous devez utiliser l‟expression !b + 5 pour calculer le nouveau
contenu de la boite.
Code:
let b = ref 10 in
b := !b + 5;
print_int !b;
3-3-3 Incrémentation- Décrémentation
Pour reference appelée quantite, l‟instruction quantite := !quantite + 1
s‟appelle une "incrémentation" de la référence quantite. Cette opération
´étant assez courante, il existe une fonction qui permet de faire ¸ca : incr,
qu‟on place devant le nom de la référence. Les trois instructions suivantes
sont ainsi ´équivalentes :
quantite := ! quantite + 1;
quantite := succ ! quantite ;
incr quantite ;
Introduction à la programmation
09/11/2022 60
fonctionnelle
Selon le même principe, on peut "décrémenter" une référence avec decr. Les
trois instructions suivantes sont aussi équivalentes :
quantite := ! quantite - 1;
quantite := pred ! quantite ;
decr quantite ;
RQ: Il est certes possible de faire : let b = ref (read _int()) in, mais c‟est
déconseillé, car on préfère toujours mettre une seule instruction par ligne. Donc
d‟abord on lit un entier, et ensuite on construit une boite contenant cet entier.
Introduction à la programmation
09/11/2022 61
fonctionnelle
4- Les fonctions
4-1 Principe des fonctions
4-1-1 Objectif
Les boucles for permettent de condenser du code qui se répète, `a condition
que les expressions répétées soient placées les unes à la suite des autres et ne
différèrent que par la valeur d‟un entier (le compteur). Voici un cas où une
boucle for ne nous permet pas de condenser le code :
for colonne = 1 to 10 do
print_string "X";
done ;
for colonne = 1 to 10 do
print_string "#";
done ;
Pourtant, trois lignes sont répétées deux fois dans ce code, `a une seule
différence près, à savoir ce qui est placé juste après le print string.
Introduction à la programmation
09/11/2022 62
fonctionnelle
Pour mettre en commun tout le code qui est répété, on va utiliser une fonction. Le
concept de fonction est extrêmement puissant et fondamental en programmation,
et c‟est pourquoi on va y consacrer tout le chapitre.
Introduction à la programmation
09/11/2022 63
fonctionnelle
Prenons des exemples de la vie courante.
1) Un robot qui fait le ménage va :
• ramasser un papier avec le nom de la pièce `a nettoyer,
• déposer rien du tout.
2) Un robot qui choisit un disque au hasard dans le placard va :
• ramasser aucun objet,
• déposer un CD.
3) Un robot chargé de trouver tous les fichiers contenant un mot donné va :
• ramasser un mot,
• déposer un certain nombre de noms de fichiers.
On n‟aura pas besoin de robots qui retournent plusieurs objets. En effet, il
est toujours possible de retourner une liste d‟objets, et cette liste compte
alors pour un seul objet. Dans l‟exemple 3, si on considère que le robot
retourne une liste de noms de fichier, alors il ne retourne qu‟un seul objet.
Tous nos robots retourneront donc zéro ou un seul objet. Note : on verra
plus tard comment gérer des listes d‟objets.
Introduction à la programmation
09/11/2022 64
fonctionnelle
4-1-3 Utilisation
Avant de pouvoir utiliser une fonction, il faut d‟abord la déclarer, c‟est-`a-
dire donner les plans de fabrication du robot associé. Pour cela, il faut :
• lui donner un nom pour pouvoir l‟utiliser plus tard (on nomme la
fonction),
• lui expliquer quels objets elle doit ramasser (la fonction prend des
arguments).
• lui donner les instructions qu‟elle doit effectuer (c‟est le corps de la
fonction),
• lui dire les objets qu‟elle doit déposer (la fonction retourne des valeurs).
Une fois la fonction créée, on pourra l‟appeler autant de fois que l‟on
voudra. Pour cela :
• on écrit le nom de la fonction,
• on place des objets séparés par des espaces, qui seront les arguments de
la fonction.
Par exemple, si la fonction s‟appelle mafonction et que l‟on veut l‟appeler
avec pour arguments l‟entier 2 et le texte "ici", on écrira pour appeler la
fonction :
Introduction à la programmation
09/11/2022 65
fonctionnelle
mafonction 2 "ici «
Deux cas se présentent alors.
1) Si la fonction ne retourne pas d‟objet, l‟appel `a la fonction est considère
comme une instruction, et on la terminera par un point-virgule :
mafonction 2 "ici ";
2) Si la fonction retourne un objet, on peut nommer cet objet avec un let :
let x = mafonction 2 "ici " in
Ou bien on peut utiliser directement cet objet. Par exemple si l‟objet
retourné par mafonction est un entier, on pourra faire :
print_int ( mafonction 2 " ici ");
Introduction à la programmation
09/11/2022 66
fonctionnelle
for colonne = 1 to 10 do
print_string "X";
done ;
for colonne = 1 to 10 do
print_string "#";
done ;
La différence entre les deux codes est juste la chaîne après le print string. Pour
faire apparaitre clairement que tout le reste du code est identique dans les deux
cas, on va réécrire le code en nommant une variable motif égale `a la chaîne en
question.
La première boucle devient :
let motif = "X" in
for colonne = 1 to 10 do
print_string motif ;
done ;
Introduction à la programmation
09/11/2022 67
fonctionnelle
Tandis que la seconde devient :
let motif = "#" in
for colonne = 1 to 10 do
print_string motif ;
done ;
RQ:L‟idée est d‟utiliser une fonction qui va prendre en argument une certaine
chaîne nommée motif, et qui va effectuer :
for colonne = 1 to 10 do
print_string motif ;
done ;
• motif sera l‟argument (le paramètre) de la fonction;
• les trois lignes de code précédentes forment le corps de la fonction;
• notez que cette fonction ne retourne rien.
Pour nommer une fonction, on choisit toujours un nom décrivant
précisément l’action réalisée par le corps de cette fonction.
Dans notre cas, "affiche_dix_fois" est un bon nom.
Introduction à la programmation
09/11/2022 68
fonctionnelle
Pour définir une fonction, on écrit :
Syntaxe:
let (... nom de la fonction ...) (... noms des arguments ...) =
(... instructions du corps de la fonction ...)
in
Dans notre exemple, cela donne :
let affiche_dix_fois motif =
for colonne = 1 to 10 do
print_string motif ;
done ;
in
Pour appeler une fonction qui ne retourne rien, on écrit :
Syntaxe:
(... nom de la fonction ...) (... valeurs des arguments ...)
affiche_dix_fois "X"; pour l’exemple précédent.
Introduction à la programmation
09/11/2022 69
fonctionnelle
En procédant de même pour le reste du code, on remplace au final le source :
for colonne = 1 to 10 do
print_string "X";
done ;
for colonne = 1 to 10 do
print_string "#";
done ;
par cet autre source : en utilisant la fonction
let affiche_dix_fois motif =
for colonne = 1 to 10 do
print_string motif ;
done ;
in
affiche_dix_fois "X";
affiche_dix_fois "#";
Introduction à la programmation
09/11/2022 70
fonctionnelle
RQ: Ces deux sources produisent le même affichage mais ne fonctionnent pas
de la même manière.
A RETENIR:
• Une fonction doit toujours être définie avant de pouvoir d‟étre utilisée.
• N‟oubliez pas de décaler vers la droite (indenter) le corps de la fonction
et le in, pour bien visualiser où commence et où se termine la déclaration.
• N‟oubliez pas d‟ajouter une ligne vide `a la suite de la déclaration de la
fonction, afin d‟aérer convenablement le code.
• On utilisait déjà des fonctions prédéfinies utilisant un paramètre et ne
retournant rien. Par exemple print_int et print_float sont de telles fonctions.
Application: Utilisez une fonction nommée ligne avec vingt fois pour
condenser le code suivant :
Introduction à la programmation
09/11/2022 71
fonctionnelle
for colonne = 1 to 20 do
print_string "X";
done ;
print_newline ();
for colonne = 1 to 20 do
print_string "#";
done ;
print_newline ();
for colonne = 1 to 20 do
print_string "i";
done ;
print_newline ();
Introduction à la programmation
09/11/2022 72
fonctionnelle
Solution:
let ligne_avec_vingt_fois motif =
for colonne = 1 to 20 do
print_string motif ;
done ;
print_newline ();
in
ligne_avec_vingt_fois "X";
ligne_avec_vingt_fois "#";
ligne_avec_vingt_fois "i";
Introduction à la programmation
09/11/2022 73
fonctionnelle
4-2-2 Fonction avec contexte
On souhaite maintenant utiliser une fonction pour condenser le code suivant :
let nb_colonnes = read_int () in
if nb_colonnes > 5 then
begin
for colonne = 1 to nb_colonnes do
print_string " -";
done ;
end
else
begin
for colonne = 1 to nb_colonnes do
print_string ".";
done ;
end
;
Le code qu‟on peut mettre en commun, qui correspond au corps de la fonction,
est de la forme :
Introduction à la programmation
09/11/2022 74
fonctionnelle
for colonne = 1 to nb_colonnes do
print_string motif ;
done ;
On va nommer cette fonction affiche _nb _fois. Son paramètre est motif.
Voici la déclaration de la fonction affiche _nb _fois :
let affiche_nb_fois motif =
for colonne = 1 to nb_colonnes do
print_string motif ;
done ;
in
Pour utiliser cette fonction, on fera affiche_ nb _fois "-" dans le bloc du
then, et affiche _nb_ fois "." dans le bloc du else.
Pour que le programme fonctionne, il faut précéder ce code de la
déclaration de nb _colonnes et la déclaration de la fonction. Et donc ça
devient:
Introduction à la programmation
09/11/2022 75
fonctionnelle
let nb_colonnes = read_int () in
let affiche_nb_fois motif =
for colonne = 1 to nb_colonnes do
print_string motif ;
done ;
in
if nb_colonnes > 5
then affiche_nb_fois "-"
else affiche_nb_fois ".";
4-2-3 Fonction avec lecture
Essayons cette fois ci une autre variante de programme qui demande un
premier motif `a l‟utilisateur, et affiche ce motif 10 fois de suite. Ensuite il
demande un second motif `a l‟utilisateur, et l‟affiche 15 fois de suite. Voici le
code :
Introduction à la programmation
09/11/2022 76
fonctionnelle
let motif_1 = read_line () in
for colonne = 1 to 10 do
print_string motif_1 ;
done ;
print_newline ();
let motif_2 = read_line () in
for colonne = 1 to 15 do
print_string motif_2 ;
done ;
Alors le bloc répété est:
let motif = read_line () in
for colonne = 1 to nb_colonnes do
print_string motif ;
done ;
Introduction à la programmation
09/11/2022 77
fonctionnelle
Voici donc le code de la fonction, que l‟on appelle affiche_nb_motifs_choisi,
prend en paramètre nb _colonnes:
let affiche_nb_motifs_choisi nb_colonnes =
let motif = read_line () in
for colonne = 1 to nb_colonnes do
print_string motif ;
done ;
in
affiche_nb_motifs_choisi 10;
print_newline ();
affiche_nb_motifs_choisi 15;
Introduction à la programmation
09/11/2022 78
fonctionnelle
4-2-4 Fonction avec Plusieurs paramètres
Voyons maintenant une situation où un seul paramètre ne suffit plus. Il s‟agit
toujours d‟afficher une ligne formée de motifs, mais cette fois deux éléments
changent : `a la fois la longueur de la ligne et aussi le motif qui la forme. Par
exemple :
for colonne = 1 to 15 do
print_string "*";
done ;
for colonne = 1 to 19 do
print_string " -_- ";
done ;
En utilisant nb _colonnes et motif comme nom des paramètres, on a le corps
de la fonction :
for colonne = 1 to nb_colonnes do
print_string motif ;
done ;
Introduction à la programmation
09/11/2022 79
fonctionnelle
RQ: On va construire cette fonction à deux paramètres, de la même manière
que lorsqu‟il y avait un seul paramètre, à ceci près :
• lors de la déclaration de la fonction, on écrira les paramètres à la
suite, séparés par des espaces, entre le nom de la fonction et le signe égal,
• lors d‟un appel à la fonction, on donnera les valeurs des paramètres
dans l‟ordre dans lequel ils apparaissent dans la déclaration, et séparés par des
espaces.
Dans notre exemple, cela donne :
let affiche_ligne_motif nb_colonnes motif =
for colonne = 1 to nb_colonnes do
print_string motif ;
done ;
in
affiche_ligne_motif 15 "*";
affiche_ligne_motif 19 " -_- ";
Résumé:
Lorsqu‟il y a plusieurs paramètres à une fonction, on les place simplement
séparés les uns des autres par des espaces sur la même ligne.
Introduction à la programmation
09/11/2022 80
fonctionnelle
L‟ordre des paramètres qui a été choisi est nb colonnes puis motif. Mais ce
choix est arbitraire, et l‟ordre inverse fonctionne très bien également .
4-2-5 Fonction Sans paramètre
On a vu des fonctions avec un ou plusieurs paramètres. Dans cette partie, on va
s‟intéresser aux fonctions qui n‟ont aucun paramètre. La fonction effectue
alors toujours le même traitement à chaque fois qu‟elle est appelée. On a déià
un exemple de telle fonction : print_ newline, qui affiche à chaque fois qu‟on
l‟appel une nouvelle ligne.
Lorsqu‟une fonction n‟a aucun paramètre :
• on place un couple de parenthèses () entre le nom de la fonction et le
signe égal,
• pour réaliser un appel, on place aussi un couple de parenthèses () à la
suite du nom de la fonction.
Exemple: quel est le nom et le paramètre de cette fonction????
let separation () =
print_newline ();
print_string "- - - - -";
print_newline ();
in
Introduction à la programmation
09/11/2022 81
fonctionnelle
4-3 Fonctions avec retour
4-3-1 Principe
On va maintenant s‟intéresser aux fonctions qui retournent (ou renvoient) une
valeur. Le robot associé va donc prendre en argument un certain nombre de
valeurs, faire des choses avec, et à la fin déposer une valeur de retour.
Le schéma d‟une fonction qui retourne une valeur est le suivant :
let (... nom de la fonction ...) (... noms des paramètres ...) =
(... actions réalisées par la fonction ...)
(... valeur de retour ...) in
La seule différence par rapport aux fonctions qui ne retournent rien est
l‟ajout d‟une valeur sur la dernière ligne juste avant le in.
Certaines fonctions sont simples : elles ne réalisent pas d‟actions et se
contentent simplement de retourner une valeur calculée à partir des
paramètres
Introduction à la programmation
09/11/2022 82
fonctionnelle
4-3-2 Sans actions
Ecrivons une fonction qui calcule la moyenne de deux réels. La fonction
moyenne prend deux arguments réels a et b, et retourne la moyenne de ces
deux nombres qui vaut (a +. b) /. 2.0.
let moyenne a b =
(a +. b) /. 2.0 in
4-3-3 Avec actions
On se souvient du code qui permet de calculer la somme des n premiers
entiers, où n est un entier positif quelconque. On fait :
let n = ..................... in
let total = ref 0 in
for i = 1 to n do
total := ! total + i;
done ;
Introduction à la programmation
09/11/2022 83
fonctionnelle
Et à la fin, !total représente la valeur de la somme qu‟on veut. L‟objectif de
cette partie est d‟écrire une fonction qui prend en paramètre n et qui retourne
la somme des n premiers entiers. Rappelons le schéma à suivre :
let (... nom de la fonction ...) (... noms des paramètres ...) =
(... actions réalisées par la fonction ...)
(... valeur de retour ...) in
Le début de cette fonction sera logiquement : let somme_entiers n =
Les actions effectuées par la fonction sont les suivantes :
let total = ref 0 in
for i = 1 to n do
total := ! total + i;
done ;
À savoir la création de la référence, et le calcul `a l‟aide de la boucle. Quant `a
la fin de cette fonction, il s‟agit de la valeur de retour, c‟est-à-dire !total suivi
d‟un in : ! total in
Introduction à la programmation
09/11/2022 84
fonctionnelle
En mettant les trois morceaux bouts-`a-bouts, on obtient la définition de la
fonction somme_entiers :
let somme_entiers n =
let total = ref 0 in
for i = 1 to n do
total := ! total + i;
done ;
! total in
4-3-4 Retour avec if
On peut faire des tests avec des structures en if pour déterminer la valeur de
retour de la fonction. Premier exemple avec la fonction maximum, qui
retourne le plus grand des deux paramètres entiers.
let maximum a b =
if a > b
then a
else b
in
Introduction à la programmation
09/11/2022 85
fonctionnelle
Pour utiliser cette fonction, c‟est toujours le même principe :
let x = max 4 6 in
print_int x;
La valeur de retour d‟une fonction peut être le résultat d‟une structure if :
let (... nom de la fonction ...) (... noms des paramètres ...) =
(... actions de la fonction ...)
if (... condition ...)
then (... valeur de retour 1...)
else (... valeur de retour 2...)
in
Introduction à la programmation
09/11/2022 86
fonctionnelle
5- array, char, string
5-1 Tableaux
5-1-1 Principe
La force des ordinateurs est d‟être capable de réaliser un très grand nombre
de fois des tâches relativement simples, il peut s‟agir de:
faire un grand nombre de calculs ou encore,
de traiter une grande quantité de données.
Si on doit réaliser une opération sur quelques milliers d‟objets de même
type, on ne va pas s‟amuser à donner un nom diffèrent à chacun d‟entre
eux.
L‟idée d‟un tableau, array en anglais, est de donner :
un nom à ce groupe d‟objets, puis ;
de numéroter dans un certain ordre tous les objets qui appartiennent à ce
groupe.
Introduction à la programmation
09/11/2022 87
fonctionnelle
On a modélisé une référence comme étant une boite simple dans laquelle on
pouvait mettre une unique valeur modifiable.
Dans le même esprit, un tableau est une grande boite avec plusieurs
compartiments. Chaque compartiment, on dira aussi “case du tableau”, est
un peu comme une référence : on peut y mettre une valeur, et la modifier si
besoin est.
Une propriété importante à vérifier est que tous les compartiments doivent
contenir des objets de même type. On ne fabriquera que plus tard des boites
avec des compartiments de natures différentes, pouvant accueillir des objets
de types différents.
Une référence sur un entier est de type int ref, une référence sur un
flottant de type float ref.
Selon la même logique le type d‟un tableau d’entier est de type int array,
un tableau de flottants est de type float array, et un tableau de chaîne
string array.
En fait, on peut faire des tableaux contenant des valeurs de n‟importe quel
type.
Introduction à la programmation
09/11/2022 88
fonctionnelle
Le nombre de compartiments contenus dans le tableau est fixé au moment
de sa fabrication.
On appelle ce nombre la taille, la longueur, ou encore la dimension du
tableau.
Il n‟est pas possible de changer la taille d‟un tableau après sa création.
Si on veut augmenter le nombre d‟objets numérotés dans le groupe, il
faudra fabriquer un autre tableau.
Chaque compartiment est identifié par un numéro unique.
L‟élément situé dans le compartiment numéro i et dit “élément d’indice
i”.
Attention: les numéros commencent à partir de 0 et non à partir de 1.
Considérons un tableau contenant taille compartiments.
Le premier élément de ce tableau est donc d’indice 0,
le deuxième d’indice 1,
le troisième d‟indice 2,
etc...
Enfin, le dernier est d’indice taille-1 (et non pas d’indice taille puisqu‟on
ne commence pas `a 1).
Introduction à la programmation
09/11/2022 89
fonctionnelle
NB: Suivant la même démarche que pour les références, on va commencer
par:
la création des tableaux,
puis on passera à leur manipulation.
5-1.2 Création de Tableau
De même qu‟une boite ne peut pas être vide, les compartiments d‟un tableau
ne peuvent pas être vides. Pour créer un tableau, il faut donc donner les
´éléments que l‟on veut mettre dedans. Pour construire un tableau, on place
entre les symboles [| et |] les éléments du tableau, en les séparant par des
points-virgules.
Par exemple : pour construire un tableau avec des compartiments contenant
les entiers 4, 9 et 8 :
On écrit: [| 4; 9; 8 |]
Introduction à la programmation
09/11/2022 90
fonctionnelle
Détails:
• L‟élément à l’indice 0 est 4, celui à l‟indice 1 est 9, et celui à l‟indice
2 est 8.
• Ce tableau est donc de taille 3, et cette taille est définitive pour ce
tableau.
• Il contient des entiers, et ne pourra jamais contenir autre chose que des
entiers.
• Le type de ce tableau est ainsi int array.
• Les valeurs contenues par ce tableau (4, 9 et 8) seront susceptibles
d'être modifiées.
Pour nommer ce tableau, il suffit d’utiliser :
un let pour y associer un nom ;
suivit du signe égal;
ensuite du syntaxe du tableau;
et enfin de IN.
Exemple:
let mon_tableau = [| 4; 9; 8 |] in ...
Introduction à la programmation
09/11/2022 91
fonctionnelle
On a pris comme premier exemple un tableau d‟entiers, mais les tableaux
fonctionnent aussi bien avec des valeurs de n‟importe quel type.
Voici un tableau de flottants, donc de type float array :
let mon_tableau_float = [| 4.32; 3.49; 9.48; 5.33 |] in ...
On peut également créer un tableau de chaines, qui sera ainsi de type
string array :
let mon_tableau_string = [| "un "; " super "; " tableau " |] in ...
RQ:
Cette technique de création ne marche que pour de petits tableaux,
puisqu‟on ne va pas écrire à la main des milliers de valeurs côtes à côtes.
On va donc avoir besoin d‟une autre méthode pour construire les tableaux
dans des cas plus généraux.
Cette méthode consiste à utiliser une fonction nommée "Array.make",
traduit mot à mot "Tableau.fabrique".
Array correspond à ce qu‟on appellera un module.
Introduction à la programmation
09/11/2022 92
fonctionnelle
C‟est une structure qui permet de:
regrouper un certain nombre de fonctions;
mettre un peu d‟ordre dans les centaines de noms de fonctions utilisables
par le programmeur.
On retiendra de cela que toutes les fonctions de manipulations de tableaux
ont un nom qui commence par Array suivit d‟un point.
La fonction Array.make, qui permet de créer un tableau, s‟utilise avec
deux paramètres:
Le premier est la taille du tableau que l‟on souhaite créer.
Le seconde paramètre est un objet dont on va mettre une copie dans
chacune des cases du tableau que l‟on veut créer. C‟est une solution simple,
qui permet à la fois :
• de préciser le type des compartiments,
• de certifier que tous les compartiments sont de même type,
• de donner un contenu initial `a chaque compartiment.
On pourra par la suite modifier le contenu des cases comme on le souhaite.
Introduction à la programmation
09/11/2022 93
fonctionnelle
L‟expression " Array.make taille remplissage " retourne un tableau de
longueur taille, dont toutes les cases contiennent la valeur remplissage.
Exemple: let t = Array . make 5 8 in ...
let tab_test = Array . make 25 " test " in
5-1-3 Lecture
Si tab est un tableau, alors l‟expression tab.(i) représente la valeur contenue
dans sa i-éme case.
Exemple: let mon_tableau = [| 4; 9; 8 |] in ...
Ecrire un programme qui affiche les différents contenu du tableau.
Code: let mon_tableau = [| 4; 9; 8 |] in
print_int mon_tableau .(0) ;
print_newline ();
print_int mon_tableau .(1) ;
print_newline ();
print_int mon_tableau .(2) ;
Introduction à la programmation
09/11/2022 94
fonctionnelle
5-1-4 Modification
Voici comment modifier le contenu d‟une case dont on connait l‟indice dans
un tableau :
tab.(i) <- valeur
Introduction à la programmation
09/11/2022 95
fonctionnelle
Bibliographie
• John McCarthy, Recursive Functions of Symbolic Expressions and Their Computation by
Machine, Part I [archive], Communications of the ACM, Vol. 3 Issue 4, April
1960DOI:10.1145/367177.367199
Introduction à la programmation
09/11/2022 96
fonctionnelle