Skip to content
Snippets Groups Projects
Commit 3c310812 authored by COQUERY EMMANUEL's avatar COQUERY EMMANUEL
Browse files

Séance 10/02 et corrigé séance du 03/02

parent f28dcb3f
No related branches found
No related tags found
No related merge requests found
...@@ -15,10 +15,10 @@ ...@@ -15,10 +15,10 @@
| | 11h30 | TD1 Grp B | | | | | 11h30 | TD1 Grp B | | |
| 27/01 | 8h | CM2 | OCaml | [Diapositives](cm/lifpf-cm2.pdf), [Script démos](cm/cm2-demo.md) | | 27/01 | 8h | CM2 | OCaml | [Diapositives](cm/lifpf-cm2.pdf), [Script démos](cm/cm2-demo.md) |
| | 9h45 ou 11h30 | TP1 | Prise en main | [Sujet](tp/tp1.md), [corrigé](tp/tp1.ml) | | | 9h45 ou 11h30 | TP1 | Prise en main | [Sujet](tp/tp1.md), [corrigé](tp/tp1.ml) |
| 03/02 | 8h | TD2 | Lambda-Calcul | [Sujet](td/lifpf-td2-enonce.pdf) | | 03/02 | 8h | TD2 | Lambda-Calcul | [Sujet](td/lifpf-td2-enonce.pdf), [corrigé](td/lifpf-td2-correction.pdf) |
| | 9h45 ou 11h30 | TP2 | Listes | [Sujet](tp/tp2.md) | | | 9h45 ou 11h30 | TP2 | Listes | [Sujet](tp/tp2.md), [corrigé](tp/tp2.ml) |
| 10/02 | 8h | CM3 | Struct. ind. + types param. | (2024) [Diapositives](cm/lifpf-cm3.pdf) | | 10/02 | 8h | CM3 | Struct. ind. + types param. | [Diapositives](cm/lifpf-cm3.pdf) |
| | 9h45 ou 11h30 | TP3 | Arbres | (2024) [Sujet](tp/tp3.md) | | | 9h45 ou 11h30 | TP3 | Arbres | [Sujet](tp/tp3.md) |
| 17/02 | 8h | TD3 | Arbres | (2024) [Sujet](td/lifpf-td3-enonce.pdf) | | 17/02 | 8h | TD3 | Arbres | (2024) [Sujet](td/lifpf-td3-enonce.pdf) |
| | 9h45 ou 11h30 | TP4 | Arbres génériques | (2024) [Sujet](tp/tp4.md) | | | 9h45 ou 11h30 | TP4 | Arbres génériques | (2024) [Sujet](tp/tp4.md) |
| 10/03 | 8h | CM4 | Ordre sup. | (2024) [Diapositives](cm/lifpf-cm4.pdf) | | 10/03 | 8h | CM4 | Ordre sup. | (2024) [Diapositives](cm/lifpf-cm4.pdf) |
......
No preview for this file type
File added
tp/tp2.ml 0 → 100644
(**********************************************************************)
(**********************************************************************)
(* 1.1 *)
(**
Concatène 2 listes
@param l1 la première liste à concaténer
@param l2 la deuxième liste
@return la liste résultant de la concaténation de l1 avec l2
*)
let rec concatene (l1 : int list) (l2 : int list) : int list =
match l1 with [] -> l2 | x :: l1' -> x :: concatene l1' l2
;;
(* Quelques tests *)
concatene [ 1; 2; 3 ] [ 4; 5; 6 ] = [ 1; 2; 3; 4; 5; 6 ];;
concatene [] [ 4; 5; 6 ] = [ 4; 5; 6 ];;
concatene [ 1; 2; 3 ] [] = [ 1; 2; 3 ];;
concatene [] [] = []
(**********************************************************************)
(* 1.2 *)
(**
applatit prend une liste de liste et renvoie la liste resultant de la concatenation des sous-listes
@param ll la liste contenant les liste à concatener
@return la liste contenant les élements des sous-listes
*)
let rec applatit (ll : int list list) : int list =
match ll with [] -> [] | l :: ll' -> concatene l (applatit ll')
;;
(* Quelques tests *)
applatit [ [ 1; 2 ]; [ 3; 4; 5 ]; []; [ 6 ] ] = [ 1; 2; 3; 4; 5; 6 ];;
applatit [ [ 1 ] ] = [ 1 ];;
applatit [ [] ] = [];;
applatit [] = []
(**
applatit2 prend une liste de liste et renvoie la liste resultant de la concatenation des sous-listes.
applatit2 n'utilise pas concatene
@param ll la liste contenant les liste à concatener
@return la liste contenant les élements des sous-listes
*)
let rec applatit2 (ll : int list list) : int list =
match ll with
| [] -> []
| [] :: ll' -> applatit2 ll'
| (n :: l') :: ll' -> n :: applatit2 (l' :: ll')
;;
(* Quelques tests *)
applatit2 [ [ 1; 2 ]; [ 3; 4; 5 ]; []; [ 6 ] ] = [ 1; 2; 3; 4; 5; 6 ];;
applatit2 [ [ 1 ] ] = [ 1 ];;
applatit2 [ [] ] = [];;
applatit2 [] = []
(**********************************************************************)
(**********************************************************************)
(* 2 *)
(**
Renverse une liste.
@param l la liste à renverse.
@return la liste renversée
*)
let renverse =
(*
Cette fonction concatène son premier argument renversé à son second
@param lr la liste à renverser
@param lc la liste à laquelle on veut concaténer des éléments
@return la concaténation de lr renversée et de lc
*)
let rec renverse_ajoute (lr : int list) (lc : int list) : int list =
match lr with
| [] -> lc
| n :: lr' ->
(* on ajoute n en tête de la liste lc et on fait l'appel récursif
qui ajoutera les autres éléments devant *)
renverse_ajoute lr' (n :: lc)
in
fun (l : int list) -> renverse_ajoute l []
(**********************************************************************)
(**********************************************************************)
(* 3.1 *)
(* Insersion dans une liste triée *)
(**
Insère un entier dans une liste triée.
@param n la valeur à insérer
@param l la liste dans laquelle on fait l'insertion
@return une nouvelle liste contenant les élément de l et n et elle-même
*)
let rec insertion (n : int) (l : int list) : int list =
match l with
| [] -> [ n ] (* on aurait pu écrire [n] *)
| k :: l' ->
if k >= n (* on veut placer n en tête de liste *) then n :: l
(* attention c'est n :: l et pas n :: l'
on aurait aussi pu écrire n :: k :: l' *)
else k :: insertion n l'
;;
(* Quelques tests*)
insertion 3 [ 1; 2; 4; 5 ] = [ 1; 2; 3; 4; 5 ];;
insertion 3 [ 1; 2; 3; 4; 5 ] = [ 1; 2; 3; 3; 4; 5 ];;
insertion 3 [ 4; 5 ] = [ 3; 4; 5 ];;
insertion 3 [ 1; 2 ] = [ 1; 2; 3 ];;
insertion 3 [] = [ 3 ]
(**********************************************************************)
(* 3.2 *)
(**
Trie une liste en utilisant l'algorithme de tri par insertion
@param l la liste à trier
@return la liste contenant les éléments de l triés
*)
let rec tri_insertion (l : int list) : int list =
match l with
| [] -> []
| n :: l' ->
(* Ici, on insère dans le reste de la liste triée *)
insertion n (tri_insertion l')
;;
(* Quelques tests *)
tri_insertion [ 1; 4; 2; 3 ] = [ 1; 2; 3; 4 ];;
tri_insertion [ 1; 2; 3; 4 ] = [ 1; 2; 3; 4 ];;
tri_insertion [ 4; 3; 2; 1 ] = [ 1; 2; 3; 4 ];;
tri_insertion [ 1 ] = [ 1 ];;
tri_insertion [] = []
(**********************************************************************)
(**********************************************************************)
(* 4.1 *)
(**
Résultat d'une recherche
*)
type resultat =
(* une valeur a été trouvée,
on associe la donnée de cette valeur au constructeur,
elle a donc le type string*)
| Trouve of string
(* On a rien trouvé, pas de donnée associée *)
| Rien
(* 4.2 *)
(**
Cherche la valeur associée à une clé dans une liste de paires (clé,valeur).
@param cle la clé
@param la la liste d'association
@return Trouve v si la paire (cle,v) est dans la liste, Rien sinon
*)
let rec cherche (cle : int) (la : (int * string) list) : resultat =
match la with
| [] -> Rien
| (cle', v) :: la' ->
if cle' = cle (* si on a trouvé la clé *) then Trouve v
else (* on cherche dans le reste de la liste *)
cherche cle la'
;;
(* Quelques tests *)
cherche 3 [ (1, "a"); (3, "b"); (5, "c") ] = Trouve "b";;
cherche 3 [ (3, "b"); (5, "c") ] = Trouve "b";;
cherche 3 [ (1, "a"); (3, "b") ] = Trouve "b";;
cherche 3 [ (5, "b"); (1, "a") ] = Rien;;
cherche 3 [] = Rien
(**********************************************************************)
(**********************************************************************)
(**
Type représentant les opérateurs binaires.
*)
type binop = Plus | Moins | Mult | Div
(**
Type représentant les morceaux d'expression.
*)
type elt_expr = Op of binop | Cst of int
(**
Type représentant les résultats.
*)
type resultat =
| Ok of int
| ErrDivZero
| ErrExpr
(**
Évalue le résultat d'une opération binaire.
Prend l'opération en argument ainsi que deux résultats.
S'il l'un des arguments est une erreur, cette (une de ces)
erreur est renvoyée comme résultat.
@param op l'opération à effectuer
@param a1 la première valeur à passer à op
@param a2 la deuxième valeur à passer à op
@return le réultat de l'opération ou une erreur le cas échéant
*)
(* 5.1 *)
let eval_op (op : binop) (a1 : resultat) (a2 : resultat) : resultat =
match (a1, a2) with
| Ok v1, Ok v2 -> (
match op with
| Plus -> Ok (v1 + v2)
| Moins -> Ok (v1 - v2)
| Mult -> Ok (v1 * v2)
| Div -> if v2 = 0 then ErrDivZero else Ok (v1 / v2))
| Ok _, err -> err
| err, _ -> err
;;
(* Quelques tests *)
eval_op Plus (Ok 1) (Ok 2) = Ok 3;;
eval_op Moins (Ok 2) (Ok 3) = Ok (-1);;
eval_op Div (Ok 3) (Ok 0) = ErrDivZero;;
eval_op Div (Ok 5) (Ok 2) = Ok 2;;
eval_op Mult (Ok 7) (Ok 6) = Ok 42;;
eval_op Plus ErrDivZero (Ok 5) = ErrDivZero;;
eval_op Mult ErrExpr (Ok 4) = ErrExpr;;
eval_op Div (Ok 5) ErrExpr = ErrExpr;;
eval_op Moins (Ok 4) ErrDivZero = ErrDivZero;;
eval_op Plus ErrDivZero ErrExpr = ErrDivZero
(**********************************************************************)
(* 5.2 *)
(**
Évalue une suite d'expressions et donne la liste des résultats
@param la liste d'éléments d'expression formant la liste suite d'expressions
@return le résultat de l'évaluation des expressions
*)
let rec eval_expr (le : elt_expr list) : resultat list =
match le with
| [] -> []
| Cst n :: le' -> Ok n :: eval_expr le'
| Op op :: le' -> (
match eval_expr le' with
| r1 :: r2 :: rl -> eval_op op r1 r2 :: rl
| _ -> [ ErrExpr ])
;;
(* Quelques tests *)
eval_expr [ Cst 3 ] = [ Ok 3 ];;
eval_expr [ Op Mult; Cst 3; Cst 2 ] = [ Ok 6 ];;
eval_expr [ Op Div; Cst 7; Cst 3 ] = [ Ok 2 ];;
eval_expr [ Op Moins; Cst 3; Cst 1 ] = [ Ok 2 ];;
eval_expr [ Op Plus; Op Div; Cst 7; Cst 3 ] = [ ErrExpr ];;
eval_expr [ Op Plus; Op Div; Cst 7; Cst 3; Cst 5 ] = [ Ok 7 ];;
eval_expr [ Op Plus; Op Div; Cst 7; Op Moins; Cst 2; Cst 2; Cst 3 ]
= [ ErrDivZero ]
;;
eval_expr [ Op Plus; Cst 3; Cst 5; Op Moins; Cst 2; Cst 7 ] = [ Ok 8; Ok (-5) ]
...@@ -2,15 +2,11 @@ ...@@ -2,15 +2,11 @@
**Lire complètement** chaque partie avant de la coder. **Lire complètement** chaque partie avant de la coder.
## 1. Retour sur le TP2 ## 1. Arbres binaires
Finir les exercices du [TP2](tp2.md) jusqu'à 4.2 inclus.
## 2. Arbres binaires
Dans cette partie on va travailler sur les arbres binaires. Dans cette partie on va travailler sur les arbres binaires.
### 2.1 Quelques définitions simples ### 1.1 Quelques définitions simples
> Définir un type `arbre_bin` pour représenter les arbres binaires d'entiers (type `int`) avec un constructeur `ABVide` pour l'arbre vide et un constructeur `ABNoeud` pour les noeuds interne (qui contiendra un `int` et les deux arbres fils). > Définir un type `arbre_bin` pour représenter les arbres binaires d'entiers (type `int`) avec un constructeur `ABVide` pour l'arbre vide et un constructeur `ABNoeud` pour les noeuds interne (qui contiendra un `int` et les deux arbres fils).
> Définir également quelques variables globales d'arbres binaires pour faciliter le test des fonctions à venir. > Définir également quelques variables globales d'arbres binaires pour faciliter le test des fonctions à venir.
...@@ -25,7 +21,9 @@ assert (taille_ab ab2 = 2);; ...@@ -25,7 +21,9 @@ assert (taille_ab ab2 = 2);;
> Définir la fonction `produit_ab` qui effectue le produit des éléments d'un arbre binaire d'`int`. On prendra la convention que le produit d'un arbre vide est 1 (expliquer pourquoi on a choisi cette valeur). Tester la fonction avec des `assert`. > Définir la fonction `produit_ab` qui effectue le produit des éléments d'un arbre binaire d'`int`. On prendra la convention que le produit d'un arbre vide est 1 (expliquer pourquoi on a choisi cette valeur). Tester la fonction avec des `assert`.
### 2.2 Arbres binaires de recherche Prévenez votre chargé de TP pour qu'il valide la partie 1.1.
### 1.2 Arbres binaires de recherche
Quelques rappels sur les arbres binaires de recherche: Quelques rappels sur les arbres binaires de recherche:
...@@ -33,7 +31,7 @@ Quelques rappels sur les arbres binaires de recherche: ...@@ -33,7 +31,7 @@ Quelques rappels sur les arbres binaires de recherche:
- Pour insérer un élément dans un arbre binaire de recherche on peut l'insérer récursivement à droite ou à gauche selon qu'il est plus petit ou plus grand que l'élément du noeud dans lequel on veut faire l'insersion. - Pour insérer un élément dans un arbre binaire de recherche on peut l'insérer récursivement à droite ou à gauche selon qu'il est plus petit ou plus grand que l'élément du noeud dans lequel on veut faire l'insersion.
- Dans un parcours _infixe_ d'un arbre binaire, on regarde d'abord les éléments du fils gauche, puis l'élément du noeud, puis les éléments du fils droit. Si on effectue un parcours infixe d'un arbre binaire de recherche, alors on visite les éléments de l'arbre **dans l'ordre croissant**. - Dans un parcours _infixe_ d'un arbre binaire, on regarde d'abord les éléments du fils gauche, puis l'élément du noeud, puis les éléments du fils droit. Si on effectue un parcours infixe d'un arbre binaire de recherche, alors on visite les éléments de l'arbre **dans l'ordre croissant**.
#### 2.2.1 Insertion #### Insertion
> Écrire une fonction `insere_arbre_bin_recherche` qui insère une élément dans un arbre binaire de recherche. Précisez en commentaire ce qui est fait lorsque l'élément à ajouter est déjà présent dans l'arbre. > Écrire une fonction `insere_arbre_bin_recherche` qui insère une élément dans un arbre binaire de recherche. Précisez en commentaire ce qui est fait lorsque l'élément à ajouter est déjà présent dans l'arbre.
...@@ -41,7 +39,11 @@ On rappelle que dans le cadre de l'UE, on ne fait **pas** de modification en pla ...@@ -41,7 +39,11 @@ On rappelle que dans le cadre de l'UE, on ne fait **pas** de modification en pla
> Tester `insere_arbre_bin_recherche` en utilisant `assert`. > Tester `insere_arbre_bin_recherche` en utilisant `assert`.
#### 2.2.2 Transformation d'arbre Prévenez votre chargé de TP pour qu'il valide la partie 1.2.
### 1.3 Tri
#### 1.3.1 Transformation d'arbre en liste
> Écrire une fonction `list_of_arbre_bin` qui calcule la liste contenant les éléments d'un arbre binaire. Cette liste devra correspondre à un parcours infixe de l'arbre. Ainsi, si l'arbre est _de recherche_ les entiers de la liste obtenue doivent être croissants. > Écrire une fonction `list_of_arbre_bin` qui calcule la liste contenant les éléments d'un arbre binaire. Cette liste devra correspondre à un parcours infixe de l'arbre. Ainsi, si l'arbre est _de recherche_ les entiers de la liste obtenue doivent être croissants.
...@@ -50,7 +52,7 @@ Il faudra bien réfléchir à la position de l'élément du noeud dans le résul ...@@ -50,7 +52,7 @@ Il faudra bien réfléchir à la position de l'élément du noeud dans le résul
> Tester la fonction `list_of_arbre_bin` avec `assert`. > Tester la fonction `list_of_arbre_bin` avec `assert`.
#### 2.2.3 Transformation d'arbre #### 1.3.2 Transformation inverse et tri
> Écrire la fonction `arbre_bin_rech_of_int_list` qui transforme une liste en arbre binaire **de recherche**. > Écrire la fonction `arbre_bin_rech_of_int_list` qui transforme une liste en arbre binaire **de recherche**.
...@@ -62,7 +64,9 @@ Quelle propriété des arbres est-elle utile pour prédire le résultat de l'app ...@@ -62,7 +64,9 @@ Quelle propriété des arbres est-elle utile pour prédire le résultat de l'app
> Coder la fonction `tri_abr` qui utilise des fonctions codées dans ce TP pour trier une liste d'int. Tester cette fonction avec `assert`. > Coder la fonction `tri_abr` qui utilise des fonctions codées dans ce TP pour trier une liste d'int. Tester cette fonction avec `assert`.
## 3. Évaluation d'expressions arithmétiques Prévenez votre chargé de TP pour qu'il valide la partie 1.3.
## 2. Évaluation d'expressions arithmétiques
Dans cette partie, on va implémenter un évaluateur d'expressions arithmétiques. Dans cette partie, on va implémenter un évaluateur d'expressions arithmétiques.
...@@ -82,27 +86,31 @@ type expr = ...@@ -82,27 +86,31 @@ type expr =
> Créer quelques variables globales contenant des expressions pour les tests à venir. > Créer quelques variables globales contenant des expressions pour les tests à venir.
### 3.O Affichage d'expressions simples ### 2.1 Affichage et évaluation
> Coder la fonction `string_of_expr` qui prend en argument une expression et la transforme en une chaîne de caractères, les expressions étant notées en notation infixe et complètement parenthésées, comme par exemple `"(3 + (2 * 4))"`. #### 2.1.1 Affichage d'expressions simples
> Coder la fonction `string_of_expr` qui prend en argument une expression et la transforme en une chaîne de caractères, les expressions étant notées en notation infixe et complètement parenthésées, par exemple `"(3 + (2 * 4))"`.
> >
> Tester cette fonction en utilisant `assert` et les variables globales précédement créées. > Tester cette fonction en utilisant `assert` et les variables globales précédemment créées.
### 3.1 Évaluation d'expressions simples #### 2.1.2 Évaluation d'expressions simples
> Coder la fonction `eval_expr` qui prend en argument une expression et renvoie le résultat de son évaluation (un `int`). > Coder la fonction `eval_expr` qui prend en argument une expression et renvoie le résultat de son évaluation (un `int`).
> >
> Tester cette fonction en utilisant `assert` et les variables globales précédement créées. > Tester cette fonction en utilisant `assert` et les variables globales précédemment créées.
Prévenez votre chargé de TP afin de valider la partie 2.1.
### 3.2 Division et erreurs ### 2.2 Division et erreurs
#### 3.2.1 Ajout de l'opérateur Div #### 2.2.1 Ajout de l'opérateur Div
On souhaite ajouter la division aux opérateurs possibles pour une expression. Pour cela il faut bien sûr _ajouter un constructeur_ au type `binop`. On souhaite ajouter la division aux opérateurs possibles pour une expression. Pour cela il faut bien sûr _ajouter un constructeur_ au type `binop`.
> Modifier le type `binop` pour ajouter la division. Modifier la fonction `eval_expr` pour intégrer le cas de la division sans tenir compte des problèmes de division par zéro (pour le moment). > Modifier le type `binop` pour ajouter la division. Modifier la fonction `eval_expr` pour intégrer le cas de la division sans tenir compte des problèmes de division par zéro (pour le moment).
#### 3.2.2 Gestion de la division par zéro #### 2.2.2 Gestion de la division par zéro
La division par zéro produit une erreur. La division par zéro produit une erreur.
Plutôt que de laisser l'erreur survenir lors de la division entre `int`, on va l'anticiper en gérant la possibilité qu'une expression s'évalue en une erreur et pas en un `int`. Plutôt que de laisser l'erreur survenir lors de la division entre `int`, on va l'anticiper en gérant la possibilité qu'une expression s'évalue en une erreur et pas en un `int`.
...@@ -121,15 +129,19 @@ type resultat = Ok of int | Err of eval_err ...@@ -121,15 +129,19 @@ type resultat = Ok of int | Err of eval_err
> Modifier la fonction `eval_expr` pour qu'elle renvoie un `resultat` et pas un `int`. > Modifier la fonction `eval_expr` pour qu'elle renvoie un `resultat` et pas un `int`.
Pour y arriver, on commencera par modifier la signature et renvoyer des valeurs contruites avec `Ok` pour les cas où il n'y a **pas** d'erreur. On réfléchira ensuite aux modfications nécessaires pour prendre en compte le fait que les appels récursifs produisent maintenant des `resultat` et pas des `int`. On utilisera le pattern matching pour distinguer les cas où l'évaluation d'une sous-expression produit une erreur des cas où elle se passe bien. Pour y arriver, on commencera par modifier la signature et renvoyer des valeurs construites avec `Ok` pour les cas où il n'y a **pas** d'erreur. On réfléchira ensuite aux modifications nécessaires pour prendre en compte le fait que les appels récursifs produisent maintenant des `resultat` et pas des `int`. On utilisera le pattern matching pour distinguer les cas où l'évaluation d'une sous-expression produit une erreur des cas où elle se passe bien.
Enfin on ajoutera le test de la valeur du diviseur pour produire une erreur s'il vaut zéro. Enfin on ajoutera le test de la valeur du diviseur pour produire une erreur s'il vaut zéro.
> Modifier vos tests de la fonction `eval_expr` pour les adapter aux changements précédents. Ne pas oublier de tester la division et la division par zéro. > Modifier vos tests de la fonction `eval_expr` pour les adapter aux changements précédents. Ne pas oublier de tester la division et la division par zéro.
### 3.3 Variables Prévenez votre chargé de TP pour valider la partie 2.2.
### 2.3 Variables
On souhaite ajouter la possibiliter d'utiliser des variables dans les expressions. On a besoin pour cela de deux choses: un cas supplémentaire dans le type des expressions pour pourvoir y faire apparaître une variable et un moyen de récupérer la valeur d'une variable lors de l'évaluation de l'expression. #### 2.3.1 Variables prédéfinies
On souhaite ajouter la possibilité d'utiliser des variables dans les expressions. On a besoin pour cela de deux choses: un cas supplémentaire dans le type des expressions pour pourvoir y faire apparaître une variable et un moyen de récupérer la valeur d'une variable lors de l'évaluation de l'expression.
Les variables sont représentées par leur nom dans les expressions: Les variables sont représentées par leur nom dans les expressions:
...@@ -142,7 +154,7 @@ type expr = ...@@ -142,7 +154,7 @@ type expr =
Pour représenter la valeur des variables, on va utiliser des listes d'association (comme dans le TP2). On va cependant utiliser ici les fonctions fournies par la bibliothèque standard d'OCaml. Pour représenter la valeur des variables, on va utiliser des listes d'association (comme dans le TP2). On va cependant utiliser ici les fonctions fournies par la bibliothèque standard d'OCaml.
On rappele que le type OCaml `'a option` permet de représenter une valeur (avec le constructeur `Some x``x` est la valeur) ou bien l'absence de valeur avec le constructeur `None`. On rappelle que le type OCaml `'a option` permet de représenter une valeur (avec le constructeur `Some x``x` est la valeur) ou bien l'absence de valeur avec le constructeur `None`.
La fonction [`List.assoc_opt`](https://v2.ocaml.org/api/List.html#1_Associationlists) permet de chercher la valeur associée à une clé dans une liste d'association, c'est-à-dire dans une liste de paires (clé,valeur). C'est la version généralisée de la fonction `cherche` du TP2. La fonction [`List.assoc_opt`](https://v2.ocaml.org/api/List.html#1_Associationlists) permet de chercher la valeur associée à une clé dans une liste d'association, c'est-à-dire dans une liste de paires (clé,valeur). C'est la version généralisée de la fonction `cherche` du TP2.
...@@ -154,7 +166,7 @@ Pourquoi a-t-on ajouté le constructeur `VarNonDef` au type `eval_err` ? ...@@ -154,7 +166,7 @@ Pourquoi a-t-on ajouté le constructeur `VarNonDef` au type `eval_err` ?
> Modifier vos tests pour les ajuster aux changements précédents. Ajouter des tests pour les variables. > Modifier vos tests pour les ajuster aux changements précédents. Ajouter des tests pour les variables.
### 3.4 Let ### 2.3.2 Let
On va terminer en ajouter le constructeur `Let` aux expressions, comme `let var = expr1 in expr2` de OCaml. Ce constructeur va prendre un nom de variable (`string`) et **deux** expressions. La première est l'expression à évaluer pour obtenir la valeur de la variable. La deuxième expression sera utilisée pour calculer le résultat du `Let`. Ce résultat est simplement le résultat de cette expression évaluée avec les valeurs de variables utilisées pour évaluer le `Let` auxquelles on a ajouté la valeur de la variable du `Let`. On va terminer en ajouter le constructeur `Let` aux expressions, comme `let var = expr1 in expr2` de OCaml. Ce constructeur va prendre un nom de variable (`string`) et **deux** expressions. La première est l'expression à évaluer pour obtenir la valeur de la variable. La deuxième expression sera utilisée pour calculer le résultat du `Let`. Ce résultat est simplement le résultat de cette expression évaluée avec les valeurs de variables utilisées pour évaluer le `Let` auxquelles on a ajouté la valeur de la variable du `Let`.
...@@ -167,8 +179,10 @@ type expr = ...@@ -167,8 +179,10 @@ type expr =
``` ```
Par exemple pour évaluer l'expression `Let ("x", Cst 3, Binop (Plus, Cst 2, Var "x"))`, avec comme valeur de variables `[("y",42)]`, on évalue d'abord `Cst 3` avec les valeurs de variables `[("y",42)]`. Par exemple pour évaluer l'expression `Let ("x", Cst 3, Binop (Plus, Cst 2, Var "x"))`, avec comme valeur de variables `[("y",42)]`, on évalue d'abord `Cst 3` avec les valeurs de variables `[("y",42)]`.
On obient alors comme résultat `Ok 3`. On obtient alors comme résultat `Ok 3`.
On évalue alors `Binop (Plus, Cst 2, Var "x")` avec comme valeurs de variables `[("x", 3), ("y",42)]`. On évalue alors `Binop (Plus, Cst 2, Var "x")` avec comme valeurs de variables `[("x", 3), ("y",42)]`.
On obient alors `Ok 5` qui sera le résultat de l'évaluation du `Let`. On obtient alors `Ok 5` qui sera le résultat de l'évaluation du `Let`.
> Apporter les modifications nécessaires à la fonction `eval_expr` et ajouter les tests pour gérer le `Let`.
> Apporter les modification nécessaires à la fonction `eval_expr` et ajouter les tests pour gérer le `Let`. Prévenez votre chargé de TP pour valider la partie 2.3.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment