Bases de programmation en Caml Option informatique 2016-2017 Remarque préliminaire • Vous êtes amenés à être des spécialistes en informatique, Remarque préliminaire • Vous êtes amenés à être des spécialistes en informatique, • donc vous, vous pouvez apprendre deux langages différents, Remarque préliminaire • Vous êtes amenés à être des spécialistes en informatique, • donc vous, vous pouvez apprendre deux langages différents, • sans les confondre, Remarque préliminaire • Vous êtes amenés à être des spécialistes en informatique, • donc vous, vous pouvez apprendre deux langages différents, • sans les confondre, • ni dans la syntaxe, ni dans leurs particularités. Remarque préliminaire • Vous êtes amenés à être des spécialistes en informatique, • donc vous, vous pouvez apprendre deux langages différents, • sans les confondre, • ni dans la syntaxe, ni dans leurs particularités. • Ce ne sera pas une excuse... Recommandations d’écriture • Mettre un espace de part et d’autre de tout opérateur : a = b Recommandations d’écriture • Mettre un espace de part et d’autre de tout opérateur : a = b • Coller la virgule ou le point virgule au terme précédent, et mettre un espace après : [1; 2; 3] Recommandations d’écriture • Mettre un espace de part et d’autre de tout opérateur : a = b • Coller la virgule ou le point virgule au terme précédent, et mettre un espace après : [1; 2; 3] • Coller le terme après la parenthèse/crochet ouvrante et la parenthèse/crochet fermante au terme précédent : (1, 2, 3) Recommandations d’écriture • Mettre un espace de part et d’autre de tout opérateur : a = b • Coller la virgule ou le point virgule au terme précédent, et mettre un espace après : [1; 2; 3] • Coller le terme après la parenthèse/crochet ouvrante et la parenthèse/crochet fermante au terme précédent : (1, 2, 3) • Utiliser des noms de variables parlants ; Recommandations d’écriture • Mettre un espace de part et d’autre de tout opérateur : a = b • Coller la virgule ou le point virgule au terme précédent, et mettre un espace après : [1; 2; 3] • Coller le terme après la parenthèse/crochet ouvrante et la parenthèse/crochet fermante au terme précédent : (1, 2, 3) • Utiliser des noms de variables parlants ; • Utiliser la possibilité de commenter le code ; (* mon commentaire *) en Caml ; Recommandations d’écriture • Mettre un espace de part et d’autre de tout opérateur : a = b • Coller la virgule ou le point virgule au terme précédent, et • • • • mettre un espace après : [1; 2; 3] Coller le terme après la parenthèse/crochet ouvrante et la parenthèse/crochet fermante au terme précédent : (1, 2, 3) Utiliser des noms de variables parlants ; Utiliser la possibilité de commenter le code ; (* mon commentaire *) en Caml ; Indenter le texte pour la lisibilité (indentation non significative) ; Recommandations d’écriture • Mettre un espace de part et d’autre de tout opérateur : a = b • Coller la virgule ou le point virgule au terme précédent, et • • • • • mettre un espace après : [1; 2; 3] Coller le terme après la parenthèse/crochet ouvrante et la parenthèse/crochet fermante au terme précédent : (1, 2, 3) Utiliser des noms de variables parlants ; Utiliser la possibilité de commenter le code ; (* mon commentaire *) en Caml ; Indenter le texte pour la lisibilité (indentation non significative) ; Tout en minuscules (sauf exception) et sans accent ; Recommandations d’écriture • Mettre un espace de part et d’autre de tout opérateur : a = b • Coller la virgule ou le point virgule au terme précédent, et • • • • • • mettre un espace après : [1; 2; 3] Coller le terme après la parenthèse/crochet ouvrante et la parenthèse/crochet fermante au terme précédent : (1, 2, 3) Utiliser des noms de variables parlants ; Utiliser la possibilité de commenter le code ; (* mon commentaire *) en Caml ; Indenter le texte pour la lisibilité (indentation non significative) ; Tout en minuscules (sauf exception) et sans accent ; En devoir (et surtout au concours), votre code avec commentaires et explications sera lu 3 fois au maximum Recommandations d’écriture • Mettre un espace de part et d’autre de tout opérateur : a = b • Coller la virgule ou le point virgule au terme précédent, et • • • • • • • mettre un espace après : [1; 2; 3] Coller le terme après la parenthèse/crochet ouvrante et la parenthèse/crochet fermante au terme précédent : (1, 2, 3) Utiliser des noms de variables parlants ; Utiliser la possibilité de commenter le code ; (* mon commentaire *) en Caml ; Indenter le texte pour la lisibilité (indentation non significative) ; Tout en minuscules (sauf exception) et sans accent ; En devoir (et surtout au concours), votre code avec commentaires et explications sera lu 3 fois au maximum Si le correcteur ne comprend toujours pas, il passe à la question suivante... Types simples • int : attention au calcul modulo 231 ou 263 . Types simples • int : attention au calcul modulo 231 ou 263 . • float : bien penser à mettre le point partout, dans les opérateurs (sauf ** ) et dans les nombres ; Types simples • int : attention au calcul modulo 231 ou 263 . • float : bien penser à mettre le point partout, dans les opérateurs (sauf ** ) et dans les nombres ; • 1.0 +. 2.0 ou encore 1. +. 2. : Lourd au début, mais on s’y fait... Types simples • int : attention au calcul modulo 231 ou 263 . • float : bien penser à mettre le point partout, dans les opérateurs (sauf ** ) et dans les nombres ; • 1.0 +. 2.0 ou encore 1. +. 2. : Lourd au début, mais on s’y fait... • bool : les opérateurs logiques "et" et "ou" sont && (pas and qui est un mot-clé) et || Types simples • int : attention au calcul modulo 231 ou 263 . • float : bien penser à mettre le point partout, dans les opérateurs (sauf ** ) et dans les nombres ; • 1.0 +. 2.0 ou encore 1. +. 2. : Lourd au début, mais on s’y fait... • bool : les opérateurs logiques "et" et "ou" sont && (pas and qui est un mot-clé) et || • Ces opérateurs sont paresseux : évaluation du deuxième membre uniquement si nécessaire Types simples • int : attention au calcul modulo 231 ou 263 . • float : bien penser à mettre le point partout, dans les opérateurs (sauf ** ) et dans les nombres ; • 1.0 +. 2.0 ou encore 1. +. 2. : Lourd au début, mais on s’y fait... • bool : les opérateurs logiques "et" et "ou" sont && (pas and qui est un mot-clé) et || • Ces opérateurs sont paresseux : évaluation du deuxième membre uniquement si nécessaire • Mais si vous vous appuyez sur cette spécification il est impératif de le signaler ! Types simples • char et string : ce sont deux types différents Types simples • char et string : ce sont deux types différents • char entre backquotes (accent grave = ALT-GR 7) : ‘a‘ Types simples • char et string : ce sont deux types différents • char entre backquotes (accent grave = ALT-GR 7) : ‘a‘ • string entre double quote : "Bonjour chez vous !" Types simples • char et string : ce sont deux types différents • char entre backquotes (accent grave = ALT-GR 7) : ‘a‘ • string entre double quote : "Bonjour chez vous !" • n-uplets i.e. produit cartésien (1, "Coucou", true) est de type int * string * bool Types simples • char et string : ce sont deux types différents • char entre backquotes (accent grave = ALT-GR 7) : ‘a‘ • string entre double quote : "Bonjour chez vous !" • n-uplets i.e. produit cartésien (1, "Coucou", true) est de type int * string * bool • unit : le type vide qui ne contient qu’une seule valeur () . Pour les fonctions agissant par effet de bord (programmation impérative) Phrase • Caml évalue des phrases qui se terminent par un double point-virgule ;; Phrase • Caml évalue des phrases qui se terminent par un double point-virgule ;; • et répond en donnant les trois informations suivantes : Phrase • Caml évalue des phrases qui se terminent par un double point-virgule ;; • et répond en donnant les trois informations suivantes : • le nom de la variable globale qui vient d’être définie le cas échéant ou, à défaut, un simple tiret. Phrase • Caml évalue des phrases qui se terminent par un double point-virgule ;; • et répond en donnant les trois informations suivantes : • le nom de la variable globale qui vient d’être définie le cas échéant ou, à défaut, un simple tiret. • le type du résultat. Phrase • Caml évalue des phrases qui se terminent par un double point-virgule ;; • et répond en donnant les trois informations suivantes : • le nom de la variable globale qui vient d’être définie le cas échéant ou, à défaut, un simple tiret. • le type du résultat. • la valeur du résultat. Phrase • Caml évalue des phrases qui se terminent par un double point-virgule ;; • et répond en donnant les trois informations suivantes : • le nom de la variable globale qui vient d’être définie le cas échéant ou, à défaut, un simple tiret. • le type du résultat. • la valeur du résultat. • nom : type = valeur ou - : type = valeur Liaisons globales • Liaison globale par let : let a = 3;; Liaisons globales • Liaison globale par let : let a = 3;; • Ne crée pas une variable qu’on peut mettre à jour ! Liaisons globales • Liaison globale par let : let a = 3;; • Ne crée pas une variable qu’on peut mettre à jour ! • let a = 5;; crée une nouvelle liaison. La précédente est perdue Liaisons globales • Liaison globale par let : let a = 3;; • Ne crée pas une variable qu’on peut mettre à jour ! • let a = 5;; crée une nouvelle liaison. La précédente est perdue • la liaison est statique. Liaisons globales • Liaison globale par let : let a = 3;; • Ne crée pas une variable qu’on peut mettre à jour ! • let a = 5;; crée une nouvelle liaison. La précédente est perdue • la liaison est statique. • let b = a;; b ne sera pas changé si plus tard on fait une nouvelle liaison avec l’identificateur a Liaisons locales • Liaison locale par let... in : let a = 3 in a * a ; ; Liaisons locales • Liaison locale par let... in : let a = 3 in a * a ; ; • N’existe que dans l’expression suivant le in Liaisons locales • Liaison locale par let... in : let a = 3 in a * a ; ; • N’existe que dans l’expression suivant le in • Ne peut utiliser que des liaisons déjà connues Liaisons locales • Liaison locale par let... in : let a = 3 in a * a ; ; • N’existe que dans l’expression suivant le in • Ne peut utiliser que des liaisons déjà connues • Peuvent s’imbriquer let... in let ... in let ... in ... Liaisons locales • Liaison locale par let... in : let a = 3 in a * a ; ; • N’existe que dans l’expression suivant le in • Ne peut utiliser que des liaisons déjà connues • Peuvent s’imbriquer let... in let ... in let ... in ... • Liaisons simultanées (en parallèle) avec and Liaisons locales • Liaison locale par let... in : let a = 3 in a * a ; ; • N’existe que dans l’expression suivant le in • Ne peut utiliser que des liaisons déjà connues • Peuvent s’imbriquer let... in let ... in let ... in ... • Liaisons simultanées (en parallèle) avec and • let a = 3 and b = 5 in a * b ; ; Liaisons locales • Ceci calcule quelque chose, c’est une expression qui a une valeur et un type : Liaisons locales • Ceci calcule quelque chose, c’est une expression qui a une valeur et un type : • - : int = 15 Liaisons locales • Ceci calcule quelque chose, c’est une expression qui a une valeur et un type : • - : int = 15 • Contrairement à la liaison globale qui n’est pas une expression Liaisons locales • Ceci calcule quelque chose, c’est une expression qui a une valeur et un type : • - : int = 15 • Contrairement à la liaison globale qui n’est pas une expression • 1 let x = let a = 2 in a * a ;; Est autorisé Liaisons locales • Ceci calcule quelque chose, c’est une expression qui a une valeur et un type : • - : int = 15 • Contrairement à la liaison globale qui n’est pas une expression • 1 let x = let a = 2 in a * a ;; Est autorisé • 1 let a = 2 in let x = a * a ;; Ne l’est pas ! Caml est fortement typé • Caml analyse toutes les expressions avant de les évaluer Caml est fortement typé • Caml analyse toutes les expressions avant de les évaluer • et infère leur type Caml est fortement typé • Caml analyse toutes les expressions avant de les évaluer • et infère leur type • Il s’assure ainsi que les fonctions et les opérateurs sont utilisés avec les objets du bon type Caml est fortement typé • Caml analyse toutes les expressions avant de les évaluer • et infère leur type • Il s’assure ainsi que les fonctions et les opérateurs sont utilisés avec les objets du bon type • C’est contraignant parfois, mais c’est une énorme gage de sécurité à l’exécution. Caml est fortement typé • Caml analyse toutes les expressions avant de les évaluer • et infère leur type • Il s’assure ainsi que les fonctions et les opérateurs sont utilisés avec les objets du bon type • C’est contraignant parfois, mais c’est une énorme gage de sécurité à l’exécution. • Il faudra apprendre à déterminer, comme Caml , le type des expressions (exercices) Caml est fortement typé • Caml analyse toutes les expressions avant de les évaluer • et infère leur type • Il s’assure ainsi que les fonctions et les opérateurs sont utilisés avec les objets du bon type • C’est contraignant parfois, mais c’est une énorme gage de sécurité à l’exécution. • Il faudra apprendre à déterminer, comme Caml , le type des expressions (exercices) • Il n’y a pas de conversion implicite entre types Caml est fortement typé • Caml analyse toutes les expressions avant de les évaluer • et infère leur type • Il s’assure ainsi que les fonctions et les opérateurs sont utilisés avec les objets du bon type • C’est contraignant parfois, mais c’est une énorme gage de sécurité à l’exécution. • Il faudra apprendre à déterminer, comme Caml , le type des expressions (exercices) • Il n’y a pas de conversion implicite entre types • 3 + 4. est interdit ! Caml est fortement typé • Caml analyse toutes les expressions avant de les évaluer • et infère leur type • Il s’assure ainsi que les fonctions et les opérateurs sont utilisés avec les objets du bon type • C’est contraignant parfois, mais c’est une énorme gage de sécurité à l’exécution. • Il faudra apprendre à déterminer, comme Caml , le type des expressions (exercices) • Il n’y a pas de conversion implicite entre types • 3 + 4. est interdit ! • Si nécessaire il existe des fonctions de conversion explicites Caml est fortement typé • Caml analyse toutes les expressions avant de les évaluer • et infère leur type • Il s’assure ainsi que les fonctions et les opérateurs sont utilisés avec les objets du bon type • C’est contraignant parfois, mais c’est une énorme gage de sécurité à l’exécution. • Il faudra apprendre à déterminer, comme Caml , le type des expressions (exercices) • Il n’y a pas de conversion implicite entre types • 3 + 4. est interdit ! • Si nécessaire il existe des fonctions de conversion explicites • int_of_float, string_of_char,... Fonctions d’une seule variable • Déclaration : let f x = ... Fonctions d’une seule variable • Déclaration : let f x = ... • let f x = x * x;; Fonctions d’une seule variable • Déclaration : let f x = ... • let f x = x * x;; • f : int -> int = <fun> Fonctions d’une seule variable • Déclaration : let f x = ... • let f x = x * x;; • f : int -> int = <fun> • Utilisation f (3);; voire f 3;; (parenthèses inutiles ici) Fonctions d’une seule variable • Déclaration : let f x = ... • let f x = x * x;; • f : int -> int = <fun> • Utilisation f (3);; voire f 3;; (parenthèses inutiles ici) • Attention les appels de fonction sont associés à gauche Fonctions d’une seule variable • Déclaration : let f x = ... • let f x = x * x;; • f : int -> int = <fun> • Utilisation f (3);; voire f 3;; (parenthèses inutiles ici) • Attention les appels de fonction sont associés à gauche • pour calculer f (f (3)) il faut écrire f (f 3);; Fonctions d’une seule variable • Déclaration : let f x = ... • let f x = x * x;; • f : int -> int = <fun> • Utilisation f (3);; voire f 3;; (parenthèses inutiles ici) • Attention les appels de fonction sont associés à gauche • pour calculer f (f (3)) il faut écrire f (f 3);; • f f 3;; provoque une erreur Fonctions d’une seule variable • Déclaration : let f x = ... • let f x = x * x;; • f : int -> int = <fun> • Utilisation f (3);; voire f 3;; (parenthèses inutiles ici) • Attention les appels de fonction sont associés à gauche • pour calculer f (f (3)) il faut écrire f (f 3);; • f f 3;; provoque une erreur • Les opérateurs algébriques gardent cependant la préséance Fonctions d’une seule variable • Déclaration : let f x = ... • let f x = x * x;; • f : int -> int = <fun> • Utilisation f (3);; voire f 3;; (parenthèses inutiles ici) • Attention les appels de fonction sont associés à gauche • pour calculer f (f (3)) il faut écrire f (f 3);; • f f 3;; provoque une erreur • Les opérateurs algébriques gardent cependant la préséance • pour calculer f (3) + f (3) on peut écrire f 3 + f 3;; Fonctions d’une seule variable • Déclaration : let f x = ... • let f x = x * x;; • f : int -> int = <fun> • Utilisation f (3);; voire f 3;; (parenthèses inutiles ici) • Attention les appels de fonction sont associés à gauche • pour calculer f (f (3)) il faut écrire f (f 3);; • f f 3;; provoque une erreur • Les opérateurs algébriques gardent cependant la préséance • pour calculer f (3) + f (3) on peut écrire f 3 + f 3;; • En cas de doute : parenthésez vos expressions ! Fonction de plusieurs variables • Plusieurs solutions Fonction de plusieurs variables • Plusieurs solutions • En faire une fonction à une seule variable qui soit un n-uplet. Fonction de plusieurs variables • Plusieurs solutions • En faire une fonction à une seule variable qui soit un n-uplet. • Par exemple let produit1 (x, y) = x * y;; Fonction de plusieurs variables • Plusieurs solutions • En faire une fonction à une seule variable qui soit un n-uplet. • Par exemple let produit1 (x, y) = x * y;; • crée une fonction de type int * int -> int Fonction de plusieurs variables • Plusieurs solutions • En faire une fonction à une seule variable qui soit un n-uplet. • Par exemple let produit1 (x, y) = x * y;; • crée une fonction de type int * int -> int • Autre solution séparer les arguments par un simple espace Fonction de plusieurs variables • Plusieurs solutions • En faire une fonction à une seule variable qui soit un n-uplet. • Par exemple let produit1 (x, y) = x * y;; • crée une fonction de type int * int -> int • Autre solution séparer les arguments par un simple espace • let produit2 x y = x * y;; Fonction de plusieurs variables • Plusieurs solutions • En faire une fonction à une seule variable qui soit un n-uplet. • Par exemple let produit1 (x, y) = x * y;; • crée une fonction de type int * int -> int • Autre solution séparer les arguments par un simple espace • let produit2 x y = x * y;; • crée une fonction de type int -> int -> int Fonction de plusieurs variables • Plusieurs solutions • En faire une fonction à une seule variable qui soit un n-uplet. • Par exemple let produit1 (x, y) = x * y;; • crée une fonction de type int * int -> int • Autre solution séparer les arguments par un simple espace • let produit2 x y = x * y;; • crée une fonction de type int -> int -> int • Noter la différence de type qu’il faut savoir interpréter Fonction de plusieurs variables • La première forme est dite non curryfiée Fonction de plusieurs variables • La première forme est dite non curryfiée • La seconde est la forme curryfiée Fonction de plusieurs variables • La première forme est dite non curryfiée • La seconde est la forme curryfiée • Elle nous dit que produit2 est une fonction qui à un entier associe une fonction Fonction de plusieurs variables • La première forme est dite non curryfiée • La seconde est la forme curryfiée • Elle nous dit que produit2 est une fonction qui à un entier associe une fonction • qui à un entier associe un entier ! Fonction de plusieurs variables • La première forme est dite non curryfiée • La seconde est la forme curryfiée • Elle nous dit que produit2 est une fonction qui à un entier associe une fonction • qui à un entier associe un entier ! • Ainsi produit2 3;; est la fonction : y → 3 ∗ y Fonction de plusieurs variables • La première forme est dite non curryfiée • La seconde est la forme curryfiée • Elle nous dit que produit2 est une fonction qui à un entier associe une fonction • qui à un entier associe un entier ! • Ainsi produit2 3;; est la fonction : y → 3 ∗ y • C’est ce qu’on appelle une fonction partielle. Fonction anonyme • On peut créer une fonction à une seule variable sans nom par le mot clé function Fonction anonyme • On peut créer une fonction à une seule variable sans nom par le mot clé function • function x -> x * x;; est une fonction avec la même fonctionnalité que f , mais sans nom ! Fonction anonyme • On peut créer une fonction à une seule variable sans nom par le mot clé function • function x -> x * x;; est une fonction avec la même fonctionnalité que f , mais sans nom ! • Peut être utile dans certains cas où on ne veut pas créer une liaison vers la fonction, mais simplement la passer en paramètre Fonction anonyme • On peut créer une fonction à une seule variable sans nom par le mot clé function • function x -> x * x;; est une fonction avec la même fonctionnalité que f , mais sans nom ! • Peut être utile dans certains cas où on ne veut pas créer une liaison vers la fonction, mais simplement la passer en paramètre • On peut bien sûr aussi lier la fonction à un identifiant avec let : let f = function x -> x * x;; Fonction anonyme • On peut créer une fonction à une seule variable sans nom par le mot clé function • function x -> x * x;; est une fonction avec la même fonctionnalité que f , mais sans nom ! • Peut être utile dans certains cas où on ne veut pas créer une liaison vers la fonction, mais simplement la passer en paramètre • On peut bien sûr aussi lier la fonction à un identifiant avec let : let f = function x -> x * x;; • Pour les fonctions à plusieurs variables on utilise fun (en forme curryfiée forcément...) Fonction anonyme • On peut créer une fonction à une seule variable sans nom par le mot clé function • function x -> x * x;; est une fonction avec la même fonctionnalité que f , mais sans nom ! • Peut être utile dans certains cas où on ne veut pas créer une liaison vers la fonction, mais simplement la passer en paramètre • On peut bien sûr aussi lier la fonction à un identifiant avec let : let f = function x -> x * x;; • Pour les fonctions à plusieurs variables on utilise fun (en forme curryfiée forcément...) • fun x y -> x * y;; a la même fonctionnalité que produit2 mais sans nom ! Fonctions • Les fonctions sont des valeurs comme les autres Fonctions • Les fonctions sont des valeurs comme les autres • typées Fonctions • Les fonctions sont des valeurs comme les autres • typées • Peuvent être calculées, passées en paramètre, renvoyées par une fonction... Fonctions • Les fonctions sont des valeurs comme les autres • typées • Peuvent être calculées, passées en paramètre, renvoyées par une fonction... • typage associatif à droite, c’est-à-dire que Fonctions • Les fonctions sont des valeurs comme les autres • typées • Peuvent être calculées, passées en paramètre, renvoyées par une fonction... • typage associatif à droite, c’est-à-dire que • int -> (int -> (int -> int)) est équivalent à Fonctions • Les fonctions sont des valeurs comme les autres • typées • Peuvent être calculées, passées en paramètre, renvoyées par une fonction... • typage associatif à droite, c’est-à-dire que • int -> (int -> (int -> int)) est équivalent à • int -> int -> int -> int . Caml fera la simplification d’ailleurs Filtrage par motif (pattern matching) • C’est un trait extrêmement puissant de Caml ; Filtrage par motif (pattern matching) • C’est un trait extrêmement puissant de Caml ; • qui permet de faire des calculs (et définir des fonctions) par cas distincts ; Filtrage par motif (pattern matching) • C’est un trait extrêmement puissant de Caml ; • qui permet de faire des calculs (et définir des fonctions) par cas distincts ; • une première syntaxe : 1 2 3 4 5 match expr0 with | motif1 -> expr1 | motif2 -> expr2 | .............. | motifn -> exprn ;; Filtrage par motif (pattern matching) • C’est un trait extrêmement puissant de Caml ; • qui permet de faire des calculs (et définir des fonctions) par cas distincts ; • une première syntaxe : 1 2 3 4 5 match expr0 with | motif1 -> expr1 | motif2 -> expr2 | .............. | motifn -> exprn ;; • L’expression expr0 est évaluée, et sa valeur comparée au premier motif : Filtrage par motif (pattern matching) • C’est un trait extrêmement puissant de Caml ; • qui permet de faire des calculs (et définir des fonctions) par cas distincts ; • une première syntaxe : 1 2 3 4 5 match expr0 with | motif1 -> expr1 | motif2 -> expr2 | .............. | motifn -> exprn ;; • L’expression expr0 est évaluée, et sa valeur comparée au premier motif : • si cette valeur répond aux contraintes du motif, c’est expr1 qui sera évaluée en réponse au filtrage ; Filtrage par motif (pattern matching) • C’est un trait extrêmement puissant de Caml ; • qui permet de faire des calculs (et définir des fonctions) par cas distincts ; • une première syntaxe : 1 2 3 4 5 match expr0 with | motif1 -> expr1 | motif2 -> expr2 | .............. | motifn -> exprn ;; • L’expression expr0 est évaluée, et sa valeur comparée au premier motif : • si cette valeur répond aux contraintes du motif, c’est expr1 qui sera évaluée en réponse au filtrage ; • sinon, sa valeur est comparée au second motif, et ainsi de suite... Filtrage par motif (pattern matching) • C’est un trait extrêmement puissant de Caml ; • qui permet de faire des calculs (et définir des fonctions) par cas distincts ; • une première syntaxe : 1 2 3 4 5 match expr0 with | motif1 -> expr1 | motif2 -> expr2 | .............. | motifn -> exprn ;; • L’expression expr0 est évaluée, et sa valeur comparée au premier motif : • si cette valeur répond aux contraintes du motif, c’est expr1 qui sera évaluée en réponse au filtrage ; • sinon, sa valeur est comparée au second motif, et ainsi de suite... • Si aucun motif n’est reconnu, une exception Match_failure est levée. Filtrage par motif (pattern matching) • Une autre syntaxe possible avec function 1 2 3 4 5 let f = function | motif1 -> expr1 | motif2 -> expr2 | .............. | motifn -> exprn ;; Filtrage par motif (pattern matching) • Une autre syntaxe possible avec function 1 2 3 4 5 let f = function | motif1 -> expr1 | motif2 -> expr2 | .............. | motifn -> exprn ;; • Par exemple 1 # let sinc = function 2 | 0. -> 1. 3 | x -> sin ( x ) /. x ;; 4 sinc : float -> float = <fun> Filtrage par motif (pattern matching) • Une autre syntaxe possible avec function 1 2 3 4 5 let f = function | motif1 -> expr1 | motif2 -> expr2 | .............. | motifn -> exprn ;; • Par exemple 1 # let sinc = function 2 | 0. -> 1. 3 | x -> sin ( x ) /. x ;; 4 sinc : float -> float = <fun> • Noter que l’argument de la fonction n’est pas nommé juste après function , mais qu’on peut utiliser le nom du motif pour le calcul Filtrage par motif (pattern matching) • Il existe un motif particulier _ (sous la touche 8) qui correspond à toute valeur : Filtrage par motif (pattern matching) • Il existe un motif particulier _ (sous la touche 8) qui correspond à toute valeur : • Par exemple 1 # let est_nul n = match n with 2 | 0 -> true 3 | _ -> false ;; 4 est_nul : int -> bool = <fun> Filtrage gardé • On ne peut pas forcément tout contraindre par un motif. On peut alors utiliser une condition supplémentaire : une garde Filtrage gardé • On ne peut pas forcément tout contraindre par un motif. On peut alors utiliser une condition supplémentaire : une garde • syntaxe | motif when condition -> Filtrage gardé • On ne peut pas forcément tout contraindre par un motif. On peut alors utiliser une condition supplémentaire : une garde • syntaxe | motif when condition -> • Par exemple 1 # let est_pair n = match n with 2 | m when m mod 2 = 0 -> true 3 | _ -> false ;; 4 est_pair : int -> bool = <fun> Filtrage gardé • On ne peut pas utiliser un identificateur déjà utilisé dans un motif... 1 2 3 4 5 6 7 8 9 10 # let egal y x = match y with | x -> true | _ -> false ;; Entrée interactive : > | _ -> false ;; > ˆ Attention ! ce cas de filtrage est inutilie. egal : ’a -> ’b -> bool = <fun> # egal 1 " artichaut " ;; egal : bool = true Filtrage gardé • On ne peut pas utiliser un identificateur déjà utilisé dans un motif... 1 2 3 4 5 6 7 8 9 10 # let egal y x = match y with | x -> true | _ -> false ;; Entrée interactive : > | _ -> false ;; > ˆ Attention ! ce cas de filtrage est inutilie. egal : ’a -> ’b -> bool = <fun> # egal 1 " artichaut " ;; egal : bool = true • le deuxième x est un motif, ce n’est pas la valeur reçue en paramètre ! Filtrage gardé • Solution : on utilise aussi une garde 1 # let egal y x = match y with 2 | y when y = x -> true 3 | _ -> false ;; 4 egal : ’a -> ’a -> bool = <fun> Polymorphisme • Parfois certaines fonctions peuvent s’appliquer à un type quelconque (cf. la fonction egal ci-dessus) ; Polymorphisme • Parfois certaines fonctions peuvent s’appliquer à un type quelconque (cf. la fonction egal ci-dessus) ; • Ces fonctions sont dites polymorphes ; Polymorphisme • Parfois certaines fonctions peuvent s’appliquer à un type quelconque (cf. la fonction egal ci-dessus) ; • Ces fonctions sont dites polymorphes ; • Caml utilise alors un type inconnu ’a , puis ’b s’il y en a besoin d’un autre...etc.. Polymorphisme • Parfois certaines fonctions peuvent s’appliquer à un type quelconque (cf. la fonction egal ci-dessus) ; • Ces fonctions sont dites polymorphes ; • Caml utilise alors un type inconnu ’a , puis ’b s’il y en a besoin d’un autre...etc.. • Par exemple il existe deux fonctions fst et snd qui rendent respectivement le premier élément et le second élément d’un couple (2-uplet) 1 2 3 4 fst ;; fst : ’a * ’b -> ’a = <fun> snd ;; snd : ’a * ’b -> ’b = <fun> Programmation fonctionnelle • Le paradigme : on ne définit que des fonctions au sens mathématiques ; Programmation fonctionnelle • Le paradigme : on ne définit que des fonctions au sens mathématiques ; • un programme est alors une succession d’appels de fonctions Programmation fonctionnelle • Le paradigme : on ne définit que des fonctions au sens mathématiques ; • un programme est alors une succession d’appels de fonctions • Cela interdit l’utilisation de variables, de boucles for, de boucles while,... Programmation fonctionnelle • Le paradigme : on ne définit que des fonctions au sens mathématiques ; • un programme est alors une succession d’appels de fonctions • Cela interdit l’utilisation de variables, de boucles for, de boucles while,... • qui relèvent de la programmation dite impérative Programmation fonctionnelle • Le paradigme : on ne définit que des fonctions au sens mathématiques ; • un programme est alors une succession d’appels de fonctions • Cela interdit l’utilisation de variables, de boucles for, de boucles while,... • qui relèvent de la programmation dite impérative • Caml n’est pas entièrement un langage fonctionnel et propose la possibilité de programmer impérativement même s’il n’est pas vraiment conçu pour cela Programmation fonctionnelle • Dans un premier temps on ne fera que de la programmation fonctionnelle Programmation fonctionnelle • Dans un premier temps on ne fera que de la programmation fonctionnelle • Cela impose un nouveau type d’approche Programmation fonctionnelle • Dans un premier temps on ne fera que de la programmation fonctionnelle • Cela impose un nouveau type d’approche • et en particulier il peut être nécessaire voire indispensable qu’une fonction puisse s’appeler elle-même Programmation fonctionnelle • Dans un premier temps on ne fera que de la programmation fonctionnelle • Cela impose un nouveau type d’approche • et en particulier il peut être nécessaire voire indispensable qu’une fonction puisse s’appeler elle-même • Ceci relève du domaine de la récursivité Programmation fonctionnelle • Dans un premier temps on ne fera que de la programmation fonctionnelle • Cela impose un nouveau type d’approche • et en particulier il peut être nécessaire voire indispensable qu’une fonction puisse s’appeler elle-même • Ceci relève du domaine de la récursivité • que nous allons tout de suite utiliser Programmation fonctionnelle • Dans un premier temps on ne fera que de la programmation fonctionnelle • Cela impose un nouveau type d’approche • et en particulier il peut être nécessaire voire indispensable qu’une fonction puisse s’appeler elle-même • Ceci relève du domaine de la récursivité • que nous allons tout de suite utiliser • et dont nous étudierons les aspects théoriques sous peu. Récursivité • Pour qu’une fonction puisse s’appeler elle-même il faut utiliser le mot clé rec après le let 1 # let rec fact n = 2 match n with 3 | 0 -> 1 4 | _ -> n * fact ( n - 1) ;; 5 fact : int -> int = <fun> Récursivité • Pour qu’une fonction puisse s’appeler elle-même il faut utiliser le mot clé rec après le let 1 # let rec fact n = 2 match n with 3 | 0 -> 1 4 | _ -> n * fact ( n - 1) ;; 5 fact : int -> int = <fun> • Noter la structure (on verra que c’est général), de manière à ce que la succession d’appels s’arrête Récursivité • Pour qu’une fonction puisse s’appeler elle-même il faut utiliser le mot clé rec après le let 1 # let rec fact n = 2 match n with 3 | 0 -> 1 4 | _ -> n * fact ( n - 1) ;; 5 fact : int -> int = <fun> • Noter la structure (on verra que c’est général), de manière à ce que la succession d’appels s’arrête • il y a filtrage Récursivité • Pour qu’une fonction puisse s’appeler elle-même il faut utiliser le mot clé rec après le let 1 # let rec fact n = 2 match n with 3 | 0 -> 1 4 | _ -> n * fact ( n - 1) ;; 5 fact : int -> int = <fun> • Noter la structure (on verra que c’est général), de manière à ce que la succession d’appels s’arrête • il y a filtrage • le(s) premier(s) motif(s) corresponde(nt) aux cas dits de base, pour lequel on connaît la réponse sans calcul Récursivité • Pour qu’une fonction puisse s’appeler elle-même il faut utiliser le mot clé rec après le let 1 # let rec fact n = 2 match n with 3 | 0 -> 1 4 | _ -> n * fact ( n - 1) ;; 5 fact : int -> int = <fun> • Noter la structure (on verra que c’est général), de manière à ce que la succession d’appels s’arrête • il y a filtrage • le(s) premier(s) motif(s) corresponde(nt) aux cas dits de base, pour lequel on connaît la réponse sans calcul • ensuite on trouve la traduction de la relation de récurrence n! = n × (n − 1)! Récursivité • Pour qu’une fonction puisse s’appeler elle-même il faut utiliser le mot clé rec après le let 1 # let rec fact n = 2 match n with 3 | 0 -> 1 4 | _ -> n * fact ( n - 1) ;; 5 fact : int -> int = <fun> • Noter la structure (on verra que c’est général), de manière à ce que la succession d’appels s’arrête • il y a filtrage • le(s) premier(s) motif(s) corresponde(nt) aux cas dits de base, pour lequel on connaît la réponse sans calcul • ensuite on trouve la traduction de la relation de récurrence n! = n × (n − 1)! • Les appels se font successivement avec des valeurs de n strictement décroissante, ce qui fait qu’on finira par un (le) cas de base. Récursivité • On peut définir plusieurs fonctions mutuellement récursives avec le mot clé and : 1 # let rec f n = match n with 2 | 0 -> ... 3 | _ -> ... 4 and g n = match n with 5 | 0 -> ... 6 | _ -> ... ;; 7 f : int -> int = <fun> 8 g : int -> int = <fun> Récursivité • On peut définir plusieurs fonctions mutuellement récursives avec le mot clé and : 1 # let rec f n = match n with 2 | 0 -> ... 3 | _ -> ... 4 and g n = match n with 5 | 0 -> ... 6 | _ -> ... ;; 7 f : int -> int = <fun> 8 g : int -> int = <fun> • Difficulté du changement de paradigme : il va falloir arriver à penser récursif... (exercices) Gestion des erreurs • À notre niveau si on veut signaler une erreur dans l’utilisation d’une fonction Gestion des erreurs • À notre niveau si on veut signaler une erreur dans l’utilisation d’une fonction • on lèvera une exception avec l’instructiion failwith 1 # let divise x y = match y with 2 | 0. -> failwith " Division par z é ro interdite ! " 3 | _ -> x /. y ;; 4 divise : float -> float -> float