added PHashtbl.get_eq/get_hash, to access the functions;

added a function to create a PHashtbl from a module;
added PHashtbl.map
This commit is contained in:
Simon Cruanes 2013-03-04 17:31:34 +01:00
parent 01e008256c
commit 25a7d33985
3 changed files with 62 additions and 2 deletions

View file

@ -51,6 +51,17 @@ let create ?(max_load=0.8) ?(eq=fun x y -> x = y)
eq; eq;
hash; } hash; }
module type Hashable = sig
type t
val equal : t -> t -> bool
val hash : t -> int
end
(** Create a hashtable from the given 'typeclass' *)
let create_tc (type key) (h : (module Hashable with type t = key)) size =
let module H = (val h) in
create ~eq:H.equal ~hash:H.hash size
(** Copy of the hashtable *) (** Copy of the hashtable *)
let copy t = { let copy t = {
eq = t.eq; eq = t.eq;
@ -179,6 +190,17 @@ let fold f acc t =
done; done;
!acc !acc
(** Map, replaces values by other values *)
let map f t =
let t' = create ~eq:t.eq ~hash:t.hash (Array.length t.buckets) in
for i = 0 to Array.length t.buckets - 1 do
match t.buckets.(i) with
| (_, _, Empty) -> ()
| (k, _, Deleted) -> t'.buckets.(i) <- my_deleted k
| (k, v, Used) -> t'.buckets.(i) <- (k, f k v, Used)
done;
t'
(** Destructive filter (remove bindings that do not satisfiy predicate) *) (** Destructive filter (remove bindings that do not satisfiy predicate) *)
let filter pred t = let filter pred t =
for i = 0 to Array.length t.buckets - 1 do for i = 0 to Array.length t.buckets - 1 do
@ -201,3 +223,7 @@ let to_seq t =
(** Statistics on the table *) (** Statistics on the table *)
let stats t = (Array.length t.buckets, t.size, t.size, 0, 0, 1) let stats t = (Array.length t.buckets, t.size, t.size, 0, 0, 1)
let get_eq t = t.eq
let get_hash t = t.hash

View file

@ -25,8 +25,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
(** {1 Open addressing hashtable, with linear probing} *) (** {1 Open addressing hashtable, with linear probing} *)
type ('a, 'b) t type ('a, 'b) t = private {
(** Polymorphic hashtable *) mutable buckets : ('a * 'b * state) array;
mutable size : int;
eq : 'a -> 'a -> bool;
hash : 'a -> int;
max_load : float;
} (** A hashtable is an array of (key, value) buckets that have a state,
plus the size of the table and equality/hash functions *)
and state = Used | Empty | Deleted
(** state of a bucket *)
val create : ?max_load:float -> ?eq:('a -> 'a -> bool) -> val create : ?max_load:float -> ?eq:('a -> 'a -> bool) ->
?hash:('a -> int) -> int -> ('a, 'b) t ?hash:('a -> int) -> int -> ('a, 'b) t
@ -34,6 +42,15 @@ val create : ?max_load:float -> ?eq:('a -> 'a -> bool) ->
and must be in ]0, 1[. Functions for equality check and hashing and must be in ]0, 1[. Functions for equality check and hashing
can also be provided. *) can also be provided. *)
module type Hashable = sig
type t
val equal : t -> t -> bool
val hash : t -> int
end
val create_tc : (module Hashable with type t = 'a) -> int -> ('a, 'b) t
(** Create a hashtable from the given 'typeclass' *)
val copy : ('a, 'b) t -> ('a, 'b) t val copy : ('a, 'b) t -> ('a, 'b) t
(** Copy of the hashtable *) (** Copy of the hashtable *)
@ -61,6 +78,9 @@ val mem : ('a,_) t -> 'a -> bool
val iter : ('a -> 'b -> unit) -> ('a, 'b) t -> unit val iter : ('a -> 'b -> unit) -> ('a, 'b) t -> unit
(** Iterate on bindings *) (** Iterate on bindings *)
val map : ('a -> 'b -> 'c) -> ('a, 'b) t -> ('a, 'c) t
(** Map, replaces values by other values *)
val filter : ('a -> 'b -> bool) -> ('a, 'b) t -> unit val filter : ('a -> 'b -> bool) -> ('a, 'b) t -> unit
(** Destructive filter (remove bindings that do not satisfiy predicate) *) (** Destructive filter (remove bindings that do not satisfiy predicate) *)
@ -75,3 +95,7 @@ val to_seq : ('a, 'b) t -> ('a * 'b) Sequence.t
val stats : (_, _) t -> int * int * int * int * int * int val stats : (_, _) t -> int * int * int * int * int * int
(** Cf Weak.S *) (** Cf Weak.S *)
val get_eq : ('v, _) t -> ('v -> 'v -> bool)
val get_hash : ('v, _) t -> ('v -> int)

View file

@ -83,6 +83,16 @@ let test_filter () =
OUnit.assert_bool "mem" (PHashtbl.mem h 4); OUnit.assert_bool "mem" (PHashtbl.mem h 4);
OUnit.assert_bool "mem" (PHashtbl.mem h 2) OUnit.assert_bool "mem" (PHashtbl.mem h 2)
let test_map () =
let h = PHashtbl.create 5 in
PHashtbl.of_seq h my_seq;
let h' = PHashtbl.map (fun k v -> String.uppercase v) h in
OUnit.assert_equal (PHashtbl.length h') 4;
OUnit.assert_equal (PHashtbl.find h' 1) "A";
OUnit.assert_equal (PHashtbl.find h' 2) "B";
OUnit.assert_equal (PHashtbl.find h' 3) "C";
OUnit.assert_equal (PHashtbl.find h' 4) "D"
let suite = let suite =
"test_pHashtbl" >::: "test_pHashtbl" >:::
[ "test_add" >:: test_add; [ "test_add" >:: test_add;