TD/TP Caml n°4 : Exceptions et aspects impératifs en Objective Caml

1. Rappels et compléments de cours

Exceptions

L'utilisation du traitement d'exception a déjà été vu dans le TP CAML n°1, grâce à la fonction failwith.
# let tete = funtion
   [] -> failwith "liste vide"
   |x::_ -> x;;
val tete: 'a list -> 'a = <fun>
# tete [3;4;5];;
-:int=3
# tete [];;
Uncaught exception: Failure "liste vide"
La fonction failwith permet de définir une exception associée à une chaîne et de l'invoquer en une seule construction. On va voir ci-après comment construire ses propres exceptions et les utiliser.

Définition d'une exception

En OCaml, les exceptions se définissent avec le mot exception, mais sont identifiées comme étant du type exn. Il s'agit d'un type particulier, correspondant à un type somme extensible. Les exemples suivants permettent d'en comprendre le sens. Attention, les noms des exceptions sont des constructeurs, ils doivent commencer par une majuscule.
# exception Erreur1;;
exception Erreur1
# Erreur1;;
-:exn = Erreur1
# exception Erreur of int;;
exception Erreur of int
# Erreur 5;;
-:exn = Erreur 5
On peut aussi utiliser le constructeur prédéfini, nommé Failure qui a un argument de type string
#Failure "out";;
-:exn = Failure "out"

Déclanchement d'une exception

Le déclanchement se fait à l'aide de la focntion raise.
# let tete = function
   [] -> raise(Failure "liste vide")
   |x::_ -> x;;
val tete: 'a list -> 'a = < fun >
# tete [];;
Uncaught exception: Failure "liste vide"

Récupération d'une exception

Déclancher une exception sert à pouvoir la gérer quand elle se produit et ensuite orienter la suite du calcul. La syntaxe est basée sur la construction try expr with filtrage. Le principe d'évaluation de cette construction est le suivant : Voici un exemple où l'on construit tout d'abord une fonction incorrecte qui calcule la somme des éléments d'une liste.
# let rec somme l = List.hd(l) + somme (List.tl(l));;
val somme: int lits - > int = < gfun >
# somme [2;3;4];;
Uncaught exception: Failure "tl"
On construit maintenant une version correcte qui gère l'arrêt de la récursivité par le traitement de l'exception déclanchée précédemment. Attention, cet exemple illustrant la gestion des exceptions, n'est pas un bon exemple à suivre pour écrire des conditions d'arrêt en récursivité.
# let rec somme l =
   try(List.hd(l)+somme(List.tl(l)))with
      Failure "tl" -> 0
      | _ -> failwith("pb inconnu!");;
# somme [2;3;4];;
-:int=9

Aspects impératifs de Objective CAML

Variables mutables

Références

Les boucles

Les tableaux

Les chaînes de caractères

Les entrées/sorties

Lecture/écriture sur les entrées et sorties standards

Notions de base sur l'utilisation de fichiers

2. Exercices

Exercice 1 : Manipulation de tableaux

Rechercher les fonctions sur les tableaux (via le manuel de X. Leroy) qui permettent :

Ecrire une fonction qui inverse le contenu d'un tableau à une dimension.

Ecrire une multiplication de deux matrices.

Exercice 2 : Polynômes, tableaux et enregistrements

On représente un polynôme à coefficients réels par un tableau tel que l'élément situé à l'indice i corresponde au coefficient de xi.

Exemple :
#let p=[|3;2;1|];;
représente le polynôme p(x)=x2+2x+3.

a) Ecrire une fonction qui affiche un polynôme. Le format d'affichage du précédent polynôme sera, par exemple : x^2+2x+3.

b) Ecrire une fonction qui additionne deux polynômes.

c) Ecrire une fonction qui multiplie deux polynômes.

d) On représente maintenant un polynôme creux par une liste d'enregistrements telle que chaque enregistrement représente un monôme et contienne ainsi deux champs : le premier indique le degré du monôme et le second le coefficient.

Exemple :
#let q=[(deg=5; coef=2.);(deg=0; coef=1.)];;
représente le polynôme creux q(x)=2x5+1.

Réécrire les 3 fonctions précédentes pour ces polynômes creux.

Exercice 3 : Tri de tableaux polymorphe

Ecrire une fonction de tri par la méthode de sélection du max d'un tableau donné en argument (le max est recherché et placé en tête puis on trie le sous-tableau privé de sa tête ...). Le tri devra être polymorphe quant au type des éléments du tableau et à la relation d'ordre utilisée.