OCaml - Les listes L3 MI.

Slides:



Advertisements
Présentations similaires
La boucle for : init7.c et init71.c
Advertisements

Chapitre annexe. Récursivité
La théorie du monde est petit
Cours n° 7 Standard Template Library II.
Piles, files et listes: notions théoriques
Portée des variables VBA & Excel
Fonctions & procédures
Introduction à l’Algorithmique
Calculs de complexité d'algorithmes
LE CALCUL LITTÉRAL AU COLLÈGE
La classe String Attention ce n’est pas un type de base. Il s'agit d'une classe défini dans l’API Java (Dans le package java.lang) String s="aaa"; // s.
Chapitre 5. Description numérique d’une variable statistique.
(Classes prédéfinies – API Java)
C.
Analyse et Programmation Déclarative / Prolog
Mesures de tensions électriques Loi des tensions dans un circuit série
Activités Vocabulaire
Nicolas Bourbaki.
Calcul numérique (avec Maple)
Limites d’une fonction
Chapitre IV. Structures linéaires (piles, files, listes chaînées)
ALGORITHMES RECURSIFS
C2i Devoir2 Siqi LIU.
Objets Opérateurs Listes
Structures de données linéaires
Eléments d ’algèbre relationnelle
Récursivité.
Les méthodes en java Une méthode est un regroupement d’instructions ayant pour but de faire un traitement bien précis. Une méthode pour être utilisée.
Expressions et assignations
OCaml – Les arbres L3 MI.
Les structures de données arborescentes
II. Chaînage, SDD séquentielles
Leçon 6 : Structures de données dynamiques IUP 2 Génie Informatique Méthode et Outils pour la Programmation Françoise Greffier.
Programmation fonctionnelle Le langage LISP
Introduction à la programmation (Java)
Complément Le diagramme des classes
Les pointeurs Modes d’adressage de variables. Définition d’un pointeur. Opérateurs de base. Opérations élémentaires. Pointeurs et tableaux. Pointeurs et.
Structures de données IFT Abder Alikacem La classe string Département dinformatique et de génie logiciel Édition Septembre 2009 Département dinformatique.
Les Fonctions. Définir une fonction Sections de code indépendantes que lon peut appeler à nimporte quel moment et dans nimporte quel ordre. Bout de code.
Introduction à la programmation I Fonctions Structures de contrôle Structures de données (arrays simples et indexés) Variables locales et globales.
1 PROTOTYPE PGC++ Vecteur_3D DÉFINITION. 2 class Vecteur_3D { private : float vx, vy, vz, vw; // Représentation en coordonnées homogènes. public : Vecteur_3D();
P. Van Roy, LINF LINF1251: Algorithmes sur les Listes Peter Van Roy Département dIngénierie Informatique, UCL
Contrôle de types Les types en programmation Expressions de types Un contrôleur de types Equivalence de types Conversions de types Généricité.
Partie II Sémantique.
Sémantique dénotationnelle
COURS DE PROGRAMMATION ORIENTEE OBJET :
COURS DE PROGRAMMATION ORIENTEE OBJET :
Institut Supérieur des Etudes Technologiques de Djerba Exposé du Traitement de Données Réalisé par: Khalifa Marwa Magroun Amira Jawadi Souad L2MDW.
CSI3525: Concepts des Langages de Programmation Notes # 6: Langages de Programmation Fonctionelle II: Introduction au ML.
Affectation (d'après "Learning Python", de Mark Lutz)
Chapitre X Modèles.
Le langage C Structures de données
Ch. PAUL - Piles et Files à l'aide de listes chainées
Algorithmique Les structures Rappel L'enchaînement séquentiel
4 Introduction des objets. Les chaînes et tableaux
LES PILES ET FILES.
Programmation fonctionnelle Lambda-calcul
CSI2520  Cette fonction permet d’attribuer une valeur à une variable (set! nombre (+ 3 4)) (set! nombre (+ 1 nombre)) En SCHEME, les fonctions dont le.
REPRESENTATION DE L’INFORMATION
Le langage Racket (Lisp)
Objets Opérateurs Listes
Variables et environnement utilisateur W. Barhoumi.
Évaluation et application des fonctions Let f = function x -> ( function y -> x+y );; Type :int -> (int ->int) int -> int ->int f int.
Chapitre 3: Translation et Vecteurs
Cours LCS N°4 Présenté par Mr: LALLALI
Let rec f n = if n = 0 then true else g (n-1) g n = if n = 0 then false else f (n-1) val f : int -> bool = val g : int -> bool =
6/10/2005 © 2005 P. Van Roy. All rights reserved. 1 FSAB1402: Informatique 2 Récursion sur les Listes Peter Van Roy Département d’Ingénierie Informatique,
Philippe Gandy - 22 septembre 2015 Basé sur les notes de cours de Daniel Morin et Roch Leclerc.
Directives Ocaml Définition
IFT359 – Programmation fonctionnelle Thème 07 Fermeture, affectation ou monades 1.
Transcription de la présentation:

OCaml - Les listes L3 MI

Introduction Les listes sont un type de données très souvent utilisées en Caml. Une liste est une séquences ordonnée d'éléments d'un même type. Le type list est prédéfini en Caml.

Construire une liste On peut définir une liste directement : # let l1 = [ "What "; "a "; "wonderful "; "World !"];; val l1 : string list = ["What "; "a "; "wonderful "; "World !"] Ou constructivement, grâce à deux éléments : La liste vide [] et le constructeur d'ajout en tête :: # let l2 = [3; 4];; val l2 : int list = [3; 4] # let l3 = 1 :: l2;; val l3 : int list = [1; 3; 4]

Parcourir une liste Les fonctions List.hd et List.tl permettent d'accéder respectivement à la tête et à la queue d'une liste. # List.tl l1;; - : string list = ["a "; "wonderful "; "World !"] # List:hd l3;; - : int = 1 Remarque : les fonctions hd et tl sont définies dans le module List. La notation pointée Module.nom permet d'accéder à la valeur nom du module Module. Il est également possible d'ouvrir le module avec la directive #open List et d'utiliser ensuite les fonctions hd et tl directement.

Fonctions élémentaires sur les listes La plupart de ces fonctions opèrent par filtrage sur une liste passée en argument. Le prédicat empty renvoie true si son argument est la liste vide, false sinon : # let empty l = match l with [] -> true | x :: xs -> false;; val empty : 'a list -> bool = <fun> # empty ["here" ; "there"];; - : bool = false # empty [[1; 2]; [3; 3; 3]; []];;

pout tout 'a, 'a list -> bool Remarque sur les types Remarque : le type inféré par le compilateur pour la fonction empty est : 'a list -> bool Ici, le paramètre 'a du constructeur de type list doit être compris comme une variable de type, qui peut être remplacée par n'importe quel type lors de l'application de la fonction. En fait le type de empty peut se lire : pout tout 'a, 'a list -> bool La fonction empty est dite polymorphe. La fonction ne s'occupe pas du type des éléments de la liste, mais seulement de sa structure. La fonction peut opérer sur des listes d'éléments de n'importe quel type (int, string, int list, etc.)

La fonction length La fonction length renvoie la longueur (nombre d'éléments) d'une liste. # let rec length l = match l with [] -> 0 | x :: reste -> 1 + length reste;; val length : 'a list -> int = <fun> # length ["hello" ; "world"];; - : int = 2 # length [];; - : int = 0 La définition de la fonction length est récursive, elle dit en substance : si la liste est vide (première clause), la longueur de la liste est 0 sinon, elle est formée d'au moins un élément, suivi d'une autre liste, sa longueur est alors 1 + la longueur de cette autre liste.

La fonction rev La fonction rev "renverse" une liste, c-à-d renvoie une liste dont les éléments sont placés dans l'ordre inverse. # let rec rev l = match l with [] -> [] | x :: xs -> (rev xs) @ [x];; val rev : 'a list -> 'a list = <fun> Remarque : @ est l'opérateur de concaténation de liste # [1; 2] @ [3; 4; 5];; - : int list = [1; 2; 3; 4; 5]

La fonction member Le prédicat member teste si un élément e appartient à une liste l # let rec member e l = match l with [] -> false | x :: xs -> if e = x then true else member e xs;; val member : 'a -> 'a list -> bool = <fun> # member 2 [1; 2; 5];; - : bool = true # member "foo" ["toto"; "titi"];; - : bool = false Remarque : le polymorphisme provient ici du fait que l'opérateur = est lui même polymorphique : # (=);; - : 'a -> 'a -> bool = <fun>

La fonction list_rem La fonction list_rem retire un élément d'une liste. # let rec list_rem e l = match l with [] -> [] | x :: xs -> if e = x then xs else x :: list_rem e xs;; val list_rem : 'a -> 'a list -> 'a list = <fun> # list_rem "a" ["bc"; "a"; "def"];; - : string list = ["bc"; "def"]

Remarque sur list_rem ATTENTION : la fonction list_rem ne modifie pas la liste passée en argument mais renvoie une nouvelle liste, formée des éléments de la liste d'entrée auxquels on a ôté l'élément considéré. Cette approche est caractéristique d'un style de programmation fonctionnel, dans lequel la notion de valeur mutable ("variable") n'existe pas. # let l1 = [1; 2; 3];; val l1 : int list = [1; 2; 3] # let l2 = list_rem 2 l1;; val l2 : int list = [1; 3] # l1;; - : int list = [1; 2; 3]

Fonctionnelle - la fonction list_sum Soit la fonction list_sum, qui calcule la somme des éléments d'une liste d'entiers : # let add x y = x + y;; val add : int -> int -> int = <fun> # let rec list_sum l = match l with [] -> 0 | x :: xs -> add x (list_sum xs);; val list_sum : int list -> int = <fun> # list sum [1; 2; 3];; - : int = 6 Réductions successives lors de l'évaluation : sum list [1; 2; 3] => add 1 (sum list [2; 3]) => add 1 (add 2 (sum list [3])) => add 1 (add 2 (add 3 (sum list []))) => add 1 (add 2 (add 3 0)) => add 1 (add 2 3) => add 1 5 => 6

Fonctionnelle - la fonction list_prod Soit maintenant la fonction list_prod qui calcule, le produit des éléments d'une liste d'entiers : # let mul x y = x * y;; val mul : int -> int -> int = <fun> # let rec list_prod l = match l with [] -> 1 | x :: xs -> mul x (list_prod xs);; val list_prod : int list -> int = <fun> # list prod [4; 5; 6];; - : int = 120

Fonctionnelles Les fonctions list_sum et list_prod sont très similaires. Si les xi désignent les éléments de la liste d'entrée, f un opérateur (add pour list_sum et mul pour list_prod) et z l'élément neutre pour cet opérateur, elles calculent toutes les deux un résultat de la forme : f x1 (f x2 (... (f xn z) ...)) Ce "schéma de calcul générique" peut être formulé de la manière suivante: si la liste est vide, renvoyer z, sinon, renvoyer f x r, où x désigne la tête de la liste et r le résultat de l'application du schéma de calcul à la queue xs de cette liste. # let rec list_fold f z l = match l with [] -> z | x :: xs -> f x (list_fold f z xs);; val list_fold : ('a -> 'b -> 'b) -> 'b -> 'a list -> 'b = <fun>

Détails sur list_fold La fonction list_fold prend trois arguments : une fonction f , de type 'a -> 'b -> 'b, c-à-d un opérateur prenant un argument de type 'a, un argument de type 'b et renvoyant un résultat de type 'b, un élément de type 'b, une liste d'éléments de type 'a. Une telle fonction acceptant une autre fonction en argument est dite d'ordre supérieur (on emploie aussi parfois le terme fonctionnelle). Les fonctions list_sum et list_prod peuvent ainsi se définir simplement par spécialisation de la fonctionnelle list_fold :

Application de list_fold # let list_sum l = list_fold add 0 l;; val list_sum : int list -> int = <fun> # list_sum [1; 2; 3];; - : int = 6 # let list_prod l = list_fold mul 1 l;; val list_prod : int list -> int = <fun> # list_prod [4; 5; 6];; - : int = 120 On peut aussi appliquer list_fold à une fonction définie "à la volée", par exemple pour calculer la somme des carrés des éléments d’une liste : # list_fold (fun x y -> x * x + y) 0 [1; 2; 3; 4];; - : int = 30

Une autre fonctionnelle : map La fonctionnelle map est définie de la manière suivante : # let rec map f l = match l with [] -> [] | x :: xs -> f x :: map f xs;; val map : ('a -> 'b) -> 'a list -> 'b list = <fun> Cette fonctionnelle renvoie la liste obtenue en appliquant une fonction f à tous les éléments d'une liste l. Autrement dit : map f [x1; ... ; xn] = [f(x1); ... ; f(xn)] # map (function x -> x * x ) [1; 2; 3; 4];; - : int list = [1; 4; 9; 16]

Une autre fonctionnelle : filter La fonctionnelle filter extrait la sous-liste formée des éléments satisfaisant un prédicat p : # let rec filter p l = match l with [] -> [] | x :: xs -> if p x then x :: filter p xs else filter p xs;; val filter : ('a -> bool) -> 'a list -> 'a list = <fun> # filter (function x -> x > 4) [1; 5; 8; 2; 10];; - : int list = [5; 8; 10]