Map

Le Module Map

Ce module permet de créer des « associations ». Par exemple, disons que nous ayons des données constituées de noms d'utilisateurs avec leur mots de passe respectifs. Nous pouvons avec le module Map créer une structure de donnée associant le nom d'utilisateur à son mot de passe. De plus ce module s'aquite de sa tâche de manière assez efficace. Et aussi il le fait de manière fonctionnelle. Dans l'exemple ci-dessous nous allons réaliser des associations (mapping en anglais) du type string vers string. Cependant il est possible de faire des associations avec presque n'importe quel type de donnée.

Pour créer une structure de type Map:

# module MyUsers = Map.Make(String);;
module MyUsers : sig type key = String.t type 'a t = 'a Map.Make(String).t val empty : 'a t val is_empty : 'a t -> bool val mem : key -> 'a t -> bool val add : key -> 'a -> 'a t -> 'a t val update : key -> ('a option -> 'a option) -> 'a t -> 'a t val singleton : key -> 'a -> 'a t val remove : key -> 'a t -> 'a t val merge : (key -> 'a option -> 'b option -> 'c option) -> 'a t -> 'b t -> 'c t val union : (key -> 'a -> 'a -> 'a option) -> 'a t -> 'a t -> 'a t val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool val iter : (key -> 'a -> unit) -> 'a t -> unit val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b val for_all : (key -> 'a -> bool) -> 'a t -> bool val exists : (key -> 'a -> bool) -> 'a t -> bool val filter : (key -> 'a -> bool) -> 'a t -> 'a t val filter_map : (key -> 'a -> 'b option) -> 'a t -> 'b t val partition : (key -> 'a -> bool) -> 'a t -> 'a t * 'a t val cardinal : 'a t -> int val bindings : 'a t -> (key * 'a) list val min_binding : 'a t -> key * 'a val min_binding_opt : 'a t -> (key * 'a) option val max_binding : 'a t -> key * 'a val max_binding_opt : 'a t -> (key * 'a) option val choose : 'a t -> key * 'a val choose_opt : 'a t -> (key * 'a) option val split : key -> 'a t -> 'a t * 'a option * 'a t val find : key -> 'a t -> 'a val find_opt : key -> 'a t -> 'a option val find_first : (key -> bool) -> 'a t -> key * 'a val find_first_opt : (key -> bool) -> 'a t -> (key * 'a) option val find_last : (key -> bool) -> 'a t -> key * 'a val find_last_opt : (key -> bool) -> 'a t -> (key * 'a) option val map : ('a -> 'b) -> 'a t -> 'b t val mapi : (key -> 'a -> 'b) -> 'a t -> 'b t val to_seq : 'a t -> (key * 'a) Seq.t val to_rev_seq : 'a t -> (key * 'a) Seq.t val to_seq_from : key -> 'a t -> (key * 'a) Seq.t val add_seq : (key * 'a) Seq.t -> 'a t -> 'a t val of_seq : (key * 'a) Seq.t -> 'a t end

Bon, nous avons créé le module MyUsers en fixant le type des clefs au type string car c'est le module String qui est passé en paramètre. Maintenant entrons des données dans celui-ci. Vous vous demandez peut-être par où commencer ? Eh bien c'est très simple, nous démarrons avec une structure vide comme ceci :

# let m = MyUsers.empty;;
val m : 'a MyUsers.t = <abstr>

Hummm. Une structure d'association vide, c'est pas très intéressant, alors ajoutons-y quelques éléments :

# let m = MyUsers.add "fred" "pruneausucre" m;;
val m : string MyUsers.t = <abstr>

Nous avons créé une nouvelle association appelée m, ce faisant comme elle porte le même nom elle masquera la précédente. Cette nouvelle association a ajouté « fred » et son mot de passe « pruneausucre » à la précédente association vide. Il y a un point important ici, lorsque l'on ajoute la première donnée « pruneausucre » dans la structure d'association on fixe alors le type de donnée que cette structure peut recevoir. Ce qui signifie que l'association de notre module MyUsers est du type string to strings. Si nous désirons une association du type string vers entier ou une association du type entier vers quoi que ce soit d'autre nous devrons créer une autre structure d'association.

Maintenant ajoutons quelques données pour peupler notre association.

# let m = MyUsers.add "tom" "ilovelucy" m;;
val m : string MyUsers.t = <abstr> # let m = MyUsers.add "mark" "ocamlrules" m;;
val m : string MyUsers.t = <abstr> # let m = MyUsers.add "pete" "linux" m;;
val m : string MyUsers.t = <abstr>

Maintenant que nous avons des données dans notre association, ne serait-ce pas intéressant de voir son contenu ? Alors commençons par écrire une fonction d'affichage simple :

# let print_user key password =
    print_string (key ^ " " ^ password ^ "\n");;
val print_user : string -> string -> unit = <fun>

Nous avons ici une fonction qui prend deux chaines de caractères en paramètre, une clef et un mot de passe, et qui les affiche. Maintenant nous devons appliquer cette fonction à notre association. Voici comment le faire :

# MyUsers.iter print_user m;;
fred pruneausucre mark ocamlrules pete linux tom ilovelucy - : unit = ()

La raison qui nous a poussé à mettre nos données dans une structure d'association est probablement que nous pouvons rapidement retrouver nos données. Aussi voyons maintenant comment faire cela :

# MyUsers.find "fred" m;;
- : string = "pruneausucre"

Ceci devrait rapidement et efficacement retourner le mot de passe de Fred : "pruneausucre".