Programmation OCaml pour l`agrégation

publicité
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Programmation OCaml pour l’agrégation
Vincent Picard
IRISA - ENS Rennes
Année 2012 – 2013
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Plan
Premiers pas
Expressions et types
Environnement
Expressions conditionnelles
Fonctions
Aspects impératifs
Données structurées
Listes
Les tableaux
Les tuples
Les enregistrements
Les sommes
La programmation dans l’épreuve de modélisation
Déroulement
Bonnes habitudes
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Premiers pas
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Expressions
• Un programme OCaml est grossièrement constitué d’une suite
finie d’expressions qui sont évaluées une à une.
• Contrairement à certains langages (C, C++, Java), il n’existe
pas d’instruction en OCaml.
• Chaque expression a un type qui peut être déterminé avant
l’exécution du programme.
• Exemples
• 5 ∗ 2 + 7 est une expression de type entier int .
• true est une expression de type booléen bool.
• for i = 1 to 10 do print int i done est une expression de
type unité unit.
• On utilise deux points-virgules pour indiquer la fin d’une
expression. Voici un exemple de programme :
print string ”Bonjour !” ;;
print newline ();;
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Aperçu des types usuels
• Les types de base
• Unité : unit (une seule valeur ())
• Booléens : bool (ex : true, false )
• Entiers : int (ex : 42)
• Nombres à virgule flottante : float (ex : 1.618)
• Caractères : char (ex : ’G’)
• Chaı̂nes de caractères : string (ex : ” alice ”)
• Listes : ’a list (ex : [1; 1; 2; 3; 5; 8])
• Tableaux : ’a array (ex : [|’ b ’; ’o ’; ’b ’|] )
• Exceptions : exn (ex : Not found)
• Les types fonctionnels : ’a −> ’b
• Les types construits
• n-uplets
• enregistrements ou produits
• unions ou sommes
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Manipulation basique des expressions arithémiques et
booléennes
• Entiers
• Opérateurs : +, −, ∗, /, mod, <, <=, =, . . .
• Fonctions : abs, min, max
• Pas d’exponentiation...
• Flottants
• Opérateurs : +., −., ∗., /., ∗∗, <, <=, =, . . .
• Fonctions : sqrt, exp, log, log10, cos, . . ., acos, . . ., cosh, . . .
• Conversions : float of int , int of float , . . .
• Booléens
• Opérateurs : conjonction &&, disjonction ||
• Fonctions : négation not
• Attention à ne pas utiliser or qui est caduc et and qui a un
autre sens.
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Environnements global et locaux
• Une expression est évaluée dans un environnement qui lie
chaque identificateur à une valeur.
• Exemple : a ∗ 2 est une expression de type entier dont
l’évaluation sera 4 si a est lié à la valeur 2 et 0 si a est lié à la
valeur 0.
• Un programme est évalué dans l’environnement global. On
manipule l’environnement global grâce au mot clef let (soit en
anglais) :
let identificateur = expression ;;
• On peut créer un environnement local pour évaluer une
expression grâce aux mots clefs let et in :
let identificateur = expression1 in expression2 ;;
Si identificateur est déjà lié dans l’environnement courant, il
sera masqué par ce nouveau lien dans l’évaluation de
expression2 mais les anciens liens seront toujours présents.
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Environnements global et locaux : exemple
let a = 3;;
let b = 4;;
print int (a + b);;
let c = 10 in print int (c + 3);;
print int c ;;
let a = 4 in print int a ;;
let b = 1 in
let c = b + b in
print (a ∗ b ∗ c );;
print int b ;;
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Expressions conditionnelles
• Le branchement conditionnel est une opération fondamentale
des programmes informatiques.
• En OCaml, il prend la forme d’expressions conditionnelles :
if expression test then expression1 else expression2
• expression test doit-être de type bool.
• expression1 et expression2 doivent être du même type.
• Le type de l’expression conditionnelle est celui de expression1
(ou expression2 ).
• Sémantique : expression test est évalué ; s’il est évalué à true ,
expression1 est évalué et la valeur de l’expression conditonnelle
est celle de expression1 , sinon c’est expression2 qui est évaluée.
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Expressions conditionnelles : exemples
let a = −3;;
if a >= 0 then
print string ” positif ”
else
print string ” strictement negatif ”
;;
let b = 11 + if a > 0 then a else −a;;
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Fonctions : base
• OCaml est un langage fonctionnel : la fonction est l’objet
central du langage.
• Type d’une fonction : ’a −> ’b est le type d’une fonction
prenant comme argument une expression de type ’a et dont
l’évaluation donne une valeur de type ’b.
• Remarque : ’a et ’b peuvent être n’importe quels types, y
compris des fonctions (on parle de First-class functions).
• Appel de fonction : soit f une expression de type ’a −> ’b
(une fonction), et expression de type ’a,
f expression
est une expression de type ’b dont la valeur est l’application
de la valeur de f à la valeur de expression .
• Exemple : carre 6 vaut 36
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Fonctions : base
• Définition d’une fonction : une fonction est définie en utilisant
le mot clef function :
let identifiant = function arg −> expression
par exemple :
let carre = function x −> x ∗ x
• Remarque 1 : function est l’équivalent de λ en lambda-calcul.
• Remarque 2 : À chaque appel de fonction, expression est
évaluée dans un environnement local où arg est lié à la valeur
passée en paramètre.
• Il est recommandé d’utiliser la syntaxe simplifiée :
let identifiant arg = expression
Par exemple :
let carre x = x ∗ x
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Fonctions : récursivité
• Une fonction est récursive lorsqu’elle est appelée dans sa
propre définition.
• En OCaml, on utilise le mot clef rec après let pour que la
fonction soit liée dans l’expression qui la définit.
• Exemple classique :
let rec factorielle n =
if n <= 0 then
1
else
n ∗ ( factorielle (n − 1))
;;
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Fonctions : plusieurs arguments
• En OCaml, on construit une fonction à n arguments par une
fonction à 1 argument renvoyant la fonction partielle des n − 1
autres arguments (etc. . .), c’est la curryfication.
• Exemple : norme d’un vecteur (x, y)
let norme = function x −> function y −> sqrt (x ∗. x +. y ∗. y)
• Le type de norme est alors float −> float −> float avec
associativité à droite ( float −> (float −> float)).
• Un appel de fonction possible est norme 3 5 qui peut se lire
(norme 3) 5 : l’associativité se fait à gauche. (Remarque :
norme 3 est aussi un appel valide)
• Il est recommandé d’utiliser la syntaxe simplifiée :
let norme x y = sqrt (x ∗. x +. y ∗. y)
• Le mot clef fun sert également à écrire facilement des
fonctions curryfiées :
let norme = fun x y −> sqrt (x ∗. x +. y ∗. y)
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Fonctions : un exemple
(∗g(x) = 2xˆ2 + 3x + 5 ∗)
let g x = 2. ∗. x ∗∗ 2. +. 3. ∗. x +. 5.;;
(∗ Operateur de derivation ∗)
let epsilon = 1e−5;;
let d f x = ((f (x +. epsilon )) −. (f x)) /. epsilon ;;
let g’ = d g;;
let g ’’ = d g ’;;
print float (g’ 1.);; (∗ Resultat : 7.00002000009 ∗)
print float (g ’’ 3.14);; (∗ Resultat : 3.99992927669 ∗)
• Cet exemple illustre la puissance de la curryfication.
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Aspects impératifs
• OCaml est un langage multi-paradigme et permet une
programmation de style impératif.
• Classiquement, un programme impératif est une suite
d’instructions exécutées une à une.
• En OCaml, certaines expressions peuvent être assimilées à des
instructions. Elles n’ont pas de valeur à proprement parler
mais elles ont un effet sur l’état du système :
• Affichage d’un message à l’écran
• Ecriture dans un fichier
• Changement de l’état mémoire (cf tableaux, références,
champs mutable)
On parle d’effets de bord.
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Aspects impératifs
• On se sert du type unit (possédant une seule valeur () ) pour
typer le résultat d’une fonction ne renvoyant rien. De même
on utilisera le type unit pour écrire une fonction ne prenant
aucun argument.
• Exemples :
• print string est de type string −> unit
• print newline est de type unit −> unit
• Syntaxe pour écrire une fonction ne prenant pas d’argument :
let rire () =
print string ”Hahahahaha”
;; (∗ type : unit −> unit ∗)
rire ();;
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Aspects impératifs : opérateur de séquencement
• Lorsqu’on veut écrire une suite d’ “instructions”, on se sert de
l’opérateur de séquencement :
expression1 ; expression2
est une expression du même type que expression2 .
• Sémantique : expression1 est évaluée et sa valeur est ignorée,
puis expression2 est évaluée et sa valeur est retournée.
• Remarque : le séquencement n’est donc utile que si
l’évaluation de expression1 produit un effet de bord.
• Associativité à droite : expr1; expr2; expr3 ;; est équivalent à
expr1; (expr2; expr3 );; . Seule la valeur de la dernière
expression est retournée.
• Attention : ne pas confondre avec ;; qui est un terminateur.
• Exemple :
let rire mechant () = print string ”Mouhahaha”; print newline ();;
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Aspects impératifs : références
• L’utilisation de ”données modifiables” simplifie parfois
l’écriture de certains progammes.
• OCaml introduit la notion de référence qui est une valeur
permettant la lecture et l’écriture dans la mémoire d’une
donnée.
• Une référence a un type : elle ne permet de lire/écrire que une
donnée de ce type.
• Utilisation
• Création : let ma ref = ref
valeur initiale ;; : créé une
référence de même type que valeur initiale contenant
initialement la valeur de valeur initiale
• Lecture : !ma ref (! se prononce bang) : renvoie la valeur
contenue dans la référence
• Ecriture : maref := nouvelle valeur (expression de type unit)
• Pratique : incr et decr pour incrémenter et décrémenter une
référence sur un entier.
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Aspects impératifs : la boucle
for
• Syntaxe
for id = debut (to|downto) fin do expr done
• Cette expression est de type unit
• expr devrait être de type unit et provoquer un effet de bord.
• id est lié localement dans expr pour toutes les valeurs entières
entre debut et fin .
• On utilisera largement for pour parcourir les tableaux (et les
matrices).
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Aspects impératifs : la boucle
while
• Syntaxe
while condition do expr done
• Cette expression est de type unit
• expr devrait être de type unit et provoquer un effet de bord.
• condition est une expression booléenne évaluée avant chaque
itération : si elle est vraie on exécute la boucle sinon non.
• En général, condition fait référence à des données en mémoire
qui sont modifiées par effet de bord dans expr.
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Aspects impératifs : exemple
let racine pas x =
let estimation = ref 0. in
while (! estimation ∗∗ 2. < x) do
estimation := ! estimation +. pas;
done;
! estimation
;;
let racine pas x =
let rec cherche approx =
if (approx ∗∗ 2. < x) then
cherche (approx +. pas)
else
approx
in
cherche 0.
;;
• Une programmation impérative peut rendre certains
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Données structurées
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Les listes
• Les listes servent à manipuler un ensemble ordonné de données
de même type. Seul le premier élément est accessible en temps
constant. Il est facile d’ajouter un élément dans une liste.
• Type : ’a list
• Construction
• directe : [3; 5; 7], [] (liste vide)
• constructeur (::) :
tete :: queue
• tete est un élément de type ’a
• queue est un élément de type ’a list
• Exemple : 1.5::[2.4; 1.0] est la liste [1.5; 2.4; 1.0]
• concaténation liste1 @ liste2 . Coût = longueur de liste1 .
• Manipulation
• Le filtrage
• Obtenir la
• Obtenir la
• Obtenir la
par motifs (pattern matching)
tête : List .hd
queue d’une liste non vide : List . tl
longueur : List . length
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Le filtrage par motifs
• Le filtrage par motifs est un mécanisme permettant de
décomposer facilement des données structurées et de choisir
les actions appropriées en fonction des données.
• Syntaxe (c’est une expression)
match expression with
| motif1 −> expr1
| motif2 −> expr2
| ...
| motifn −> exprn
• Sémantique : expression est comparée à chaque motif dans
l’ordre. Dès qu’un motif correspond à expression , l’expression
résultat associée est retournée.
• Remarque : comme pour le if , expr1, . . .expr2 doivent être de
même type.
• Le filtrage doit être exhaustif : tous les cas doivent être
traités.
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Le filtrage par motifs : les listes
• motif tete :: motif queue est un exemple de motif décomposant
une liste. La queue étant elle-même une liste, il y a donc
récursivité des motifs.
• Exemples
Syntaxe simplifiée
let rec somme l = match l with
| [] −> 0
| t :: q −> t + (somme q)
;;
let rec somme = function
| [] −> 0
| t :: q −> t + (somme q)
;;
• Les identifiants utilisés dans un motif sont liés dans
l’expression associée par le filtrage.
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Le filtrage par motifs : les listes
•
(tiret bas) est le motif universel : il filtre n’importe quelle
expression :
let tete l = match l with
| t :: −> t
| [] −> failwith ” liste vide”
;;
• Utilisation de la récursivité des motifs et d’un autre type de
motif de listes.
let somme3 = function
| a :: b :: c :: −> a + b + c
| [a; b] −> a + b
| [a] −> a
| [] −> 0
;;
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Les tableaux
• Un tableau sert à représenter un nombre fixe de données de
même type et ordonnées. Chaque donnée est accessible en
temps constant.
• ’a array
• Construction
• Directe : [| ”un”; ”deux”; ” trois ” |]
• Bibliothèque : Array.make taille valeur initiale
• Les tableaux se manipulent par effets de bord :
• Lecture : t .(5) (indexation à partir de 0)
• Modification : t .(5) <− 3 de type unit
• Taille : Array. length t
• Les chaı̂nes de caractères sont équivalentes à des tableaux de
caractères mais on utilise les crochets [] pour lire et modifier
une lettre.
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Les tableaux : les matrices
• Les matrices sont des tableaux de tableaux.
• Elles doivent être créées impérativement par la commande :
Array.make matrix lignes colonnes valeur initiale .
• Pourquoi
Array.make lignes (Array.make colonnes valeur initiale )
ne marche pas ? Écrivez une version correcte de make matrix.
• Lecture : m.(i ).( j ) .
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Les tuples
• Ils servent à manipuler les couples, triplets, . . .
• Type : ’a ∗ ’b ∗ ’c ∗ . . .
• Création :
• (5, 6) de type int ∗ int
• (”Age”, 35) de type string ∗ int
• Lecture :
• Pour les couples seulement : fst , snd
• Filtrage par motif : match triplet with (a, b, c) −> ...
• Filtrage par motif (syntaxe simplifiée) :
let (a, b, c) = triplet in ...
• Exemple
type complexe = float ∗ float ;;
let module complexe =
let (x, y) = complexe in
(x ∗∗ 2. +. y ∗∗ 2.) ∗∗ 0.5
;;
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Les enregistrements
• Ils sont équivalents aux tuples mais les données sont
étiquetées.
• Voici un exemple :
type complexe = {re: float ; im: float };;
let z = {re = 3.; im = 4.};;
let module z = (z.re ∗∗ 2. + z.im ∗∗ 2.) ∗∗ 0.5 in
module z;;
• Noter la différence entre la création du type et d’une valeur de
ce type.
• Les motifs d’enregistrement peuvent être lacunaires :
let partie reelle = function
| {re = x} −> x
;;
(le filtrage est toujours exhaustif !)
• Possibilité de rendre les champs mutable (modifiable avec
<−).
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Les sommes ou unions
• Les sommes permettent de manipuler des données pouvant
prendre des types différents.
• Elles sont utilisées pour manipuler les arbres et pluq
généralement les structures définies par induction.
• Exemple
type arbre bin = Feuille | Noeud of arbre binaire ∗ arbre binaire ;;
Feuille ;;
Noeud (Noeud (Feuille, Feuille ), Feuille );;
• Les sommes sont manipulées par filtrage :
let rec taille = function
| Feuille −> 1
| Noeud (g, d) −> 1 + (taille g) + ( taille d)
;;
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Le polymorphisme, c’est pas sorcier
• Fonction polymorphe : elle manipule un ensemble de types.
Exemple : List . length manipule les listes d’entiers, de
caractères, . . .Elle est de type ’a list −> int. ’a est une
”variable muette de type”.
• L’inférence de type de OCaml choisira toujours le type le plus
général. Exemple :
let rec taille = function [] −> 0 | :: q −> 1 + (taille q );;
est de type ’a list −> int.
• Le type liste est paramétré. On peut construire un type
paramétré comme ceci :
type (’a, ’b) arbre etiquete =
| Feuille of ’a
| Noeud of ((’a ,’ b) arbre etiquete ) ∗ ’b ∗ ((’ a, ’b) arbre etiquete )
;;
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Exercices
Proposez un (ou des) type(s) adapté(s) pour représenter
• les coordonnées d’un point ;
• un graphe ;
• une formule de la logique propositionnelle ;
• une fiche d’informations personnelles (nom, prénom, . . .) ;
• un arbre ternaire ;
• une séquence ADN (suite de symboles A, T, G, C).
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
La programmation dans l’épreuve de
modélisation
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
L’exercice de programmation
• Il est obligatoire.
• Vous présenterez votre programme pendant environ
10min/40min au moment où vous le voudrez. Au bout de
30min le jury vous demandera de présenter votre programme.
• Comme le reste du concours, c’est une épreuve très codifiée. Il
est très facile de gagner des points... il est aussi facile d’en
manquer.
• Suivre le plan suivant :
1. argumenter sur le choix du langage de programmation ;
2. argumenter sur les types choisis pour représenter les données
manipulées. (surligner les types) ;
3. expliquer chaque fonction une à une (en les surlignant) ;
4. pour chaque fonction exécuter les exemples prévus ;
5. pour terminer, donner les complexités de vos fonctions.
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Pendant la préparation
• Commencer l’exercice de programmation dès que votre
compréhension du sujet le permet.
• Bien réfléchir aux types de données, à la structure.
• Prévoir des exemples pertinents d’exécution et les inclure.
• Vérifiez vos programmes au fur et à mesure grâce aux
exemples.
• Enregistrer votre travail régulièrement.
• À la fin, relancer Emacs, puis tout recompiler (si possible en
pensant à ce qu’on va dire).
• Votre code doit être lisible et compréhensible au premier coup
d’œil.
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Comment choisir les types biens ?
• Règles
• Le type devrait pouvoir représenter au mieux le domaine des
données qu’on manipule : ni plus, ni moins.
• Le type doit être adapté aux opérations utilisées.
• Conseils
• Éviter la bidouille !
• Tableau ou liste ? : taille variable ? accès direct aux éléments ?
• Exemples :
• Arc avec poids positifs ou absence d’arc entre deux sommets :
type arc = int ;; (∗ −1 si absence d’ arc ∗) NON
type arc = Arc of int | Absence;; OUI
• Ensemble de n interrupteurs ON/OFF dont on change les
états :
type leviers = bool list ;;
NON
type leviers = bool array ;;
OUI
Premiers pas
Données structurées
La programmation dans l’épreuve de modélisation
Comment rendre mon code lisible ?
• Indentation : elle doit correspondre à la ”logique” de
l’algorithme.
• Écrire de nombreuses petites fonctions espacées.
• Inclure quelques commentaires là où c’est nécessaire. Trop de
commentaires tue le commentaire.
• Choisir le bon paradigme (impératif/fonctionnel) : coder en
utilisant le paradigme naturel dans lequel l’algorithme
s’exprimme.
• Les identifiants
• Choisissez une langue et gardez ce choix.
• Préférez la syntaxe voila un identifiant .
• Ne pas hésiter à choisir un identifiant un peu long s’il permet
de comprendre le sens de l’objet désigné. Exemple :
nombre de sommets plutôt que nbsom.
Téléchargement