nsi:langages:ocaml:start
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
| nsi:langages:ocaml:start [2021/10/22 23:37] – ↷ Page déplacée de nsi:tds:serveur_web20:langages:ocaml:start à nsi:langages:ocaml:start goupillwiki | nsi:langages:ocaml:start [2022/03/22 22:46] (Version actuelle) – goupillwiki | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| - | < | + | ====== |
| - | # Présentation de OCaml | + | |
| - | *Voir [Wikipedia](https:// | + | ===== Présentation ===== |
| - | OCaml est un langage essentiellement | + | [[https:// |
| + | |||
| + | OCaml est un langage essentiellement | ||
| C'est un langage difficile à maîtriser, on va se limiter aux bases. | C'est un langage difficile à maîtriser, on va se limiter aux bases. | ||
| - | Pour faire des tests, vous pourrez utiliser un [environnement en ligne](https:// | + | Pour faire des tests, vous pourrez utiliser un [[https:// |
| - | ## Console, programme | + | ===== Console, programme |
| - | Comme souvent, vous disposez à la fois d'une console dans laaquelle | + | Comme souvent, vous disposez à la fois d'une console dans laquelle |
| Vous pouvez aussi enregistrer vos commandes dans un fichier et les exécuter ensuite. | Vous pouvez aussi enregistrer vos commandes dans un fichier et les exécuter ensuite. | ||
| - | ## Commentaires | + | ===== Les éléments |
| - | + | ||
| - | ```ocaml | + | |
| - | (* ceci est un | + | |
| - | commentare qui peut | + | |
| - | faire plusieurs lignes *) | + | |
| - | ``` | + | |
| - | + | ||
| - | ## Fin de commande | + | |
| - | + | ||
| - | Pour indiquer la fin d'une commande, on utilise `;;` | + | |
| - | + | ||
| - | ## Expressions de base | + | |
| - | + | ||
| - | D' | + | |
| - | + | ||
| - | De la même façon, `+` est l' | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | 3 + 4;; (* affiche 7 en précisant le type int*) | + | |
| - | 3. +. 4.2;; (* affiche 7.2, type float*) | + | |
| - | 3 +. 4.2;; (* Erreur ! 3 n'est pas un float*) | + | |
| - | ``` | + | |
| - | + | ||
| - | ## Assignation | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let x = 3;; | + | |
| - | ``` | + | |
| - | + | ||
| - | Le mot clé `let` peut être compris comme le *soit* des mathématiciens : *Soit x égal à 3*. | + | |
| - | + | ||
| - | **Attention :** Il n'y a pas vraiment de variables en programmation fonctionnelle. `x` ne pourra pas changer ! C'est une **constante**. | + | |
| - | + | ||
| - | > On peut néanmoins créer des variables en OCaml, mais nous n'en parlerons pas. | + | |
| - | + | ||
| - | On peut aussi définir une quantité qui n' | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let a = 2 in a+7;; | + | |
| - | (* renvoie l' | + | |
| - | ``` | + | |
| - | + | ||
| - | Dans ce qui précède, `a` n' | + | |
| - | + | ||
| - | On peut d' | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let a = 3 in let b = 11 in a * b;; | + | |
| - | (* renvoie 33 *) | + | |
| - | let r = let a = 12 in a + 15;; | + | |
| - | (* assigne la valeur 12 + 15 = 29 à r | + | |
| - | mais a n' | + | |
| - | ``` | + | |
| - | + | ||
| - | ## Conditions | + | |
| - | + | ||
| - | Opérateurs classiques. On utilise `||` pour le OU, `&& | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let x = 19;; | + | |
| - | x > 3;; (* renvoie true *) | + | |
| - | x < 25 && x < 0;; (* renvoie false *) | + | |
| - | ``` | + | |
| - | + | ||
| - | ## Bloc de test | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | if condition then instruction;; | + | |
| - | + | ||
| - | (* avec else *) | + | |
| - | if condition then instruction else instruction;; | + | |
| - | ``` | + | |
| - | + | ||
| - | ## Fonctions | + | |
| - | + | ||
| - | Évidemment, | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let f = fun x -> x+1;; | + | |
| - | (* affiche : val f: int -> int = <fun> *) | + | |
| - | ``` | + | |
| - | + | ||
| - | On a assigner à `f` une fonction en utilsant le mot-clé `fun`. Cette fonction est comme une fonction mathématique, | + | |
| - | + | ||
| - | La fonction est ici reconnue comme associant un entier à un entier. | + | |
| - | + | ||
| - | On pourra calculer : | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | f 5;; (*affiche 6*) | + | |
| - | f(5);; (*idem*) | + | |
| - | ``` | + | |
| - | + | ||
| - | Une fonction à deux variables devient un peu plus bizarre : | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let g = fun x y -> x * y;; | + | |
| - | (* renvoie val g: int -> int -> int <fun> *) | + | |
| - | g 4 13;; (* renvoie 52 *) | + | |
| - | g(4,13);; (* Erreur ! *) | + | |
| - | g 4;; (* renvoie une fonction int -> int ??? *) | + | |
| - | g(4);; (* idem *) | + | |
| - | g(4)(13);; (* renvoie 52 *) | + | |
| - | ``` | + | |
| - | + | ||
| - | Il faut comprendre que la fonction `g` reçoit d' | + | |
| - | + | ||
| - | `g 4` produit donc une fonction `y -> 4 * y`. | + | |
| - | + | ||
| - | Puisque `g(4)` est une la fonction `y -> 4 * y` on peut lui appliquer un arguement : `g(4)(13)` qui fait 52. | + | |
| - | + | ||
| - | Remarquez que les parenthèses sont inutiles et ne servent qu'à préciser une priorité en cas de besoin. | + | |
| - | + | ||
| - | *Par exemple :* | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | f f 5;; (* Erreur : le premier f essaie de prendre le 2e f comme argument *) | + | |
| - | f (f 5);; (* C'est bon, le premier f prendra le résultat de (f 5) comme argument, c'est à dire 6*) | + | |
| - | ``` | + | |
| - | + | ||
| - | Une fonction peut avoir une une fonction comme argument. Par exemple, on pourrait définir une fonction `repete` consistant, à partir d'une fonction $x \mapsto f(x)$ d' | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let repete f = fun x -> f ( f x );; | + | |
| - | (* ou, c'est équivalent *) | + | |
| - | let repete f x = f ( f x ) ;; | + | |
| - | + | ||
| - | (* Exemple d' | + | |
| - | let g = fun x -> 3 * x + 2;; | + | |
| - | let h = repete g;; | + | |
| - | (* g est la fonction x -> g(g(x)) *) | + | |
| - | g(1);; (* renvoie 5 *) | + | |
| - | g(5);; (* renvoie 17 *) | + | |
| - | h(1);; (* renvoie 17, c'est à dire g(g(1)) *) | + | |
| - | ``` | + | |
| - | + | ||
| - | ### Cas de la récurrence | + | |
| - | + | ||
| - | OCaml autorise les fonctions récurrentes mais il faut alors préciser le mot clé `rec`. | + | |
| - | + | ||
| - | Par exemple, le classique factoriel : | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let rec facto = fun n -> if n > 1 then n * (facto (n-1) ) else 1;; | + | |
| - | ``` | + | |
| - | + | ||
| - | La récurrence est le chemin privilégié. Supposez que vous souhaitiez faire la somme des `n` premiers entiers. Il serait naturel d' | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | (* attention code faux *) | + | |
| - | let n = 10;; | + | |
| - | let t = 0;; | + | |
| - | for i = 1 to n do | + | |
| - | t = t + i; | + | |
| - | done;; | + | |
| - | print_int t;; | + | |
| - | ``` | + | |
| - | + | ||
| - | Mais cela ne fonctionne pas : La commande `t = t + i` suppose de modifier la valeur de `t` ce qui n'est en principe pas possible ! Il faut passer par une récurrence : | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let rec somme = fun n -> if n = 0 then 0 else n + somme(n-1);; | + | |
| - | print_int (somme 10);; | + | |
| - | ``` | + | |
| - | + | ||
| - | La boucle est alors contenue dans l' | + | |
| - | + | ||
| - | ### Définition par cas | + | |
| - | + | ||
| - | La fonction `somme` précédente prévoyait deux cas : `n = 0` ou `n`quelconque. Il pourrait y avoir plus de cas et OCaml prévoit une syntaxe pour cela : | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let rec somme = function | + | |
| - | | 0 -> 0 | + | |
| - | | n -> n + somme(n-1) ;; | + | |
| - | ``` | + | |
| - | + | ||
| - | Il suffit d' | + | |
| - | + | ||
| - | ## Types algébriques et enregistrements | + | |
| - | + | ||
| - | On peut définir des types adaptés à nos besoins. | + | |
| - | + | ||
| - | ### types produits | + | |
| - | + | ||
| - | Supposons que nous voulions définir un type correspondant aux coordonnées entières de points. Il nous faut un doublet d' | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let coords = (2 ,3) ;; | + | |
| - | (* renvoie que coords est de type int * int *) | + | |
| - | ``` | + | |
| - | + | ||
| - | On peut enregistrer un type : | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | type coords = int * int;; | + | |
| - | ``` | + | |
| - | + | ||
| - | Mais ce n'est pas terrible car lors de la création | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let c = (4, 7);; | + | |
| - | ``` | + | |
| - | + | ||
| - | `c` n'est pas automatiquement reconnu comme de type `coords`. Il faudrait utiliser : | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | type coords = Coords of int * int;; | + | |
| - | let c = Coords(4, | + | |
| - | ``` | + | |
| - | + | ||
| - | **Attention :** on ne met pas de majuscules où on veut. La commande | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | type Coords = int * int (* erreur à cause de la majuscule *) | + | |
| - | ``` | + | |
| - | + | ||
| - | ### types sommes | + | |
| - | + | ||
| - | Quand on veut qu'une variable puisse avoir plusieurs formes. Par exemple, supposons que l'on veuille faire une fonction carré acceptant des entiers ou des flottants : | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | type number = Int of int | Float of float;; (* type number, entier ou flottant *) | + | |
| - | let carre = function | + | |
| - | | Int i -> Int(i * i) | + | |
| - | | Float f -> Float(f *. f);; | + | |
| - | + | ||
| - | carre (Float 3.5) ;; (* renvoie 12.25 *) | + | |
| - | carre (Int 3);; (* renvoie 9 *) | + | |
| - | ``` | + | |
| - | + | ||
| - | *Exemple :* On définit des types carré, rectangle losange, triangle et une fonction aire. | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | type figure = | + | |
| - | | Carre of float | + | |
| - | | Rectangle of float * float | + | |
| - | | Triangle of float * float;; | + | |
| - | let aire = function | + | |
| - | | Carre a -> a *. a | + | |
| - | | Rectangle (a, b) -> a *. b | + | |
| - | | Triangle (a, b) -> a *. b /. 2.;; | + | |
| - | ``` | + | |
| - | + | ||
| - | Ensuite on pourrait tester | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let f = (2., 5.);; | + | |
| - | aire f;; (* erreur !*) | + | |
| - | ``` | + | |
| - | + | ||
| - | OCaml ne peut détecter ce qu'est `f`. Est-ce un rectangle ? un triangle ? Il faut écrire : | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let f = Rectangle(2., | + | |
| - | aire f;; (* renvoie 10. *) | + | |
| - | ``` | + | |
| - | + | ||
| - | ### Utilisation des types sommes pour liste chaînées | + | |
| - | + | ||
| - | On veut une liste chaînée donc chaque maille est une paire avec un entier et un une flèche pointant sur le maillon suivant. Si le maillon suivant est `Nil` (*équivalent de `None`*), c'est qu'on est en fin de chaîne. | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | type maillon = Nil | Maillon of int * maillon ;; | + | |
| - | ``` | + | |
| - | + | ||
| - | On peut dès lors créer la liste : | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let a = Maillon(3, Nil);; | + | |
| - | let b = Maillon(5, a);; | + | |
| - | let c = Maillon(9, b);; (* chaîne 9 -> 5 -> 3 *) | + | |
| - | ``` | + | |
| - | + | ||
| - | Et on peut aussi créer une fonction `longueur` : | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let rec longueur = function | + | |
| - | | Nil -> 0 | + | |
| - | | Maillon (i, m) -> 1 + (longueur m);; | + | |
| - | + | ||
| - | longueur c;; (* renvoie 3*) | + | |
| - | ``` | + | |
| - | + | ||
| - | On peut remarquer que dans la défintion de `longueur` la variable `i` du cas `Maillon` n' | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let rec longueur = function | + | |
| - | | Nil -> 0 | + | |
| - | | Maillon (_, m) -> 1 + (longueur m);; | + | |
| - | ``` | + | |
| - | + | ||
| - | ### Enregistrements | + | |
| - | + | ||
| - | Ils sont comme des dictionnaires. | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | type point2D = { x : float ; y : float };; | + | |
| - | let m = { x = 3. ; y = 4.5 };; | + | |
| - | m.x (* renvoie l' | + | |
| - | ``` | + | |
| - | + | ||
| - | ## Listes | + | |
| - | + | ||
| - | On dispose d'une structure de liste. | + | |
| - | + | ||
| - | ```ocaml | + | |
| - | let x = [4; | + | |
| - | let y = 15::x;; (* liste [15;4;5;17] *) | + | |
| - | let z = 12::13;; (* erreur, pas autorisé *) | + | |
| - | ``` | + | |
| - | + | ||
| - | Avec une fonction on peut accéder au premier élément d'une liste (*head*) et à la queue (*tail*, éléments suivants). Voici un exemple donnant la somme des éléments d' | + | |
| - | ```ocaml | + | * [[.: |
| - | let rec somme = function | + | |
| - | | + | * [[.: |
| - | | + | * [[.: |
| - | tl = tail = éléments suivants.*) | + | |
| - | somme x;; (* renvoie 26 *) | + | |
| - | ``` | + | |
| - | </ | ||
nsi/langages/ocaml/start.1634938671.txt.gz · Dernière modification : de goupillwiki
