(* Cours numero 4: les aspets imperatifs et le systeme de modules*)
(* les exceptions *)
(* un type somme ouvert *)
exception Liste_zero;; let multlist_eff l = let rec aux = function [] -> 1 | (a::r) -> if a=0 then raise Liste_zero else a*(aux r) in try aux l with Liste_zero -> 0;;
(* vecteurs *)
let v = [|"a"|];;
(* acces de 0 a n-1 *)
v.(0);;
(* affectation *)
v.(0)<- "aa";; v.(0);;
(* enregistrements avec champs modifiables *)
type point = {mutable x:int};; let movepoint p dx = p.x<-p.x+dx;;
(* les cases memoire *)
type 'a ref = {mutable info: 'a};; let refval {info=v} = v;; let setref v r = r.info<-v;;
(* ce type predefini pour comodite, avec !r pour refval r et r:=v pour setref v r *)
(* un neud d'une liste avec "pointeurs" explicites *)
type 'a cell = {info: 'a; mutable next: 'a cell};;
(* exemple: liste circulaires *)
(* on utilise les noeuds ... *)
let make_cl v = let rec c = {info=v;next=c} in c;; let hd {info=v;next=l} = l.info;; let tl {next=rest} = rest;; let insert_hd v cl = let el = {info=v;next=cl.next} in cl.next<-el; cl;; let insert_tl v cl = let el = {info=v;next=cl.next} in cl.next<-el; el;; let remove_hd cl = cl.next<- cl.next.next; cl;;
(* mais cela ne marche que sur le liste non vides: *)
(* on va faire mieux ... *)
type 'a circ_list = Nil | List of 'a cell;;
(* il nous faut traiter les cas exceptionnels: *)
(* on definit des exceptions aussi *)
let insert_head v = function Nil -> List (make_cl v) | (List cl) -> List (insert_hd v cl);; let insert_tail v = function Nil -> List (make_cl v) | List cl -> List (insert_tl v cl);; exception Remove_Empty_cl;; let remove_head = function Nil -> raise Remove_Empty_cl | List cl -> let v =hd cl in let l= if cl.next==cl.next.next then Nil else List (remove_hd cl) in (v,l);;
(* cela est suffisant pour definir un type de donnee pile avec *)
(* insertion et suppression en temps constant *)
( Les Modules )
( terminologie de l'algebre: les modules sont comme des algebres: )
( ils ont une sig(nature), sont des struc(tures), et on les transforme )
( avec des foncteurs )
module type File = sig exception FileVide type 'a file val mkempty: unit -> 'a file val enqueue: 'a -> 'a file -> 'a file val dequeue: 'a file -> 'a * 'a file val isempty: 'a file -> bool end;;
module FileCLPasProtege = struct type 'a cell = {info: 'a; mutable next: 'a cell} let make_cl v = let rec c = {info=v;next=c} in c
let hd {info=v;next=l} = l.info
let insert_tl v cl = let el = {info=v;next=cl.next} in cl.next<-el; el
let remove_hd cl = cl.next<- cl.next.next; cl
type 'a circ_list = Nil | List of 'a cell
let insert_tail v = function Nil -> List (make_cl v) | List cl -> List (insert_tl v cl)
exception Remove_Empty_cl
let remove_head = function Nil -> raise Remove_Empty_cl | List cl -> let v =hd cl in let l= if cl.next==cl.next.next then Nil else List (remove_hd cl) in (v,l)
( attention aux pieges avec les effets de bord: si on ecrit )
( (hd cl, if .. then .. else ... remove_hd cl ..) )
( il peut arriver que remove_hd soit execute avant hd!!! )
exception FileVide type 'a file = 'a circ_list let mkempty () = Nil let enqueue v l = insert_tail v l let dequeue l = try remove_head l with Remove_Empty_cl -> raise FileVide let isempty = function Nil -> true | _ -> false end;;
( si on veut faire propre, on peut restraindre la signature )
module FileCL = (FileCLPasProtege : File);;
FileCL.enqueue;;
( Une autre structure de file: meme cout amortit, mais fonctionnelle )
module FileDL : File = struct type 'a file = 'a list * 'a list exception FileVide let mkempty () = [],[] let enqueue v (l1,l2) = (l1,v::l2) let dequeue = function (a::r,l) -> a,(r,l) | ([], []) -> raise FileVide | ([], l) -> let (a::l') = List.rev l in (a,(l',[])) let isempty = function ([],[]) -> true | _ -> false end;;
type 'a arbre = Empty | Node of 'a arbre * 'a * 'a arbre
module ParcLarg = functor (F:File) -> struct let rec bf f p = if F.isempty f then List.rev p else let (a,f') = F.dequeue f in match a with Empty -> bf f' p | Node(g,v,d) -> bf (F.enqueue d (F.enqueue g f')) (v::p) let parclarg a = bf (F.enqueue a (F.mkempty())) [] end;;
let b= Node (Node (Node (Empty, 4, Empty), 2, Node (Empty, 5, Empty)), 1, Node (Node (Empty, 6, Empty), 3, Node (Empty, 7, Empty)));;
( et maintenant, testons le tout! )
module PCL = ParcLarg(FileCL);; PCL.parclarg b;; module PDL = ParcLarg(FileDL);; PDL.parclarg b;;