package core_kernel

  1. Overview
  2. Docs
On This Page
  1. Usage
Legend:
Library
Module
Module type
Parameter
Class
Class type

Hashtbl is a reimplementation of the standard MoreLabels.Hashtbl. Its worst case time complexity is O(log(N)) for lookups and additions, unlike the standard MoreLabels.Hashtbl, which is O(N).

A hash table is implemented as an array of AVL trees (see Avltree). If growth_allowed (default true) is false then size is the final size of the array; the table can always hold more elements than size, but they will all go into tree nodes. If it is true (default) then the array will double in size when the number of elements in the table reaches twice the size of the array. When this happens, all existing elements will be reinserted, which can take a long time. If you care about latency, set size and growth_allowed=false if possible.

In most cases, functions passed as arguments to hash table accessors must not mutate the hash table while it is being accessed, as this will result in an exception. For example, iter and change take a function f which must not modify t. In a few cases, mutation is allowed, such as in Hashtbl.find_and_call, where all access to t is finished before the ~if_found and ~if_not_found arguments are invoked.

We have three kinds of hash table modules:

  • Hashtbl
  • Hashtbl.Poly
  • Key.Table (a class of similar modules)

There are three kinds of hash-table functions:

  • creation from nothing (create, of_alist)
  • sexp converters (t_of_sexp, sexp_of_t, and bin_io too)
  • accessors and mappers (fold, mem, find, map, filter_map, ...)

Here is a table showing what classes of functions are available in each kind of hash-table module:

                   creation     sexp-conv   accessors
    Hashtbl                                   X
    Hashtbl.Poly      X           X
    Key.Table         X           X           X'

The entry marked with X' is there for historical reasons, and may be eliminated at some point. The upshot is that one should use Hashtbl for accessors, Hashtbl.Poly for hash-table creation and sexp conversion using polymorphic compare/hash, and Key.Table for hash-table creation and sexp conversion using Key.compare and Key.hash.

Usage

For many students of OCaml, using hashtables is complicated by the functors. Here are a few tips:

  1. For a list of hashtable functions see Core_kernel.Hashtbl_intf.S.
  2. To create a hashtable with string keys use String.Table:

    let table = String.Table.create () ~size:4 in
    List.iter ~f:(fun (key, data) -> Hashtbl.set table ~key ~data)
      [ ("A", 1); ("B", 2); ("C", 3); ];
    Hashtbl.find table "C"

    Here 4 need only be a guess at the hashtable's future size. There are other similar pre-made hashtables, e.g., Int63.Table or Host_and_port.Table.

  3. To create a hashtable with a custom key type use Hashable:

    module Key = struct
      module T = struct
        type t = String.t * Int63.t [@@deriving compare, hash, sexp]
      end
      include T
      include Hashable.Make (T)
    end
    let table = Key.Table.create () ~size:4 in
    List.iter ~f:(fun (key, data) -> Hashtbl.set table ~key ~data)
      [ (("pi", Int63.zero), 3.14159);
        (("e", Int63.minus_one), 2.71828);
        (("Euler", Int63.one), 0.577215);
      ];
    Hashtbl.find table ("pi", Int63.zero)

    Performance may improve if you define equal and hash explicitly, e.g.:

    let equal (x, y) (x', y') = String.(=) x x' && Int63.(=) y y'
    let hash (x, y) = String.hash x + Int63.hash y * 65599
include Hashtbl_intf.Hashtbl with type ('a, 'b) t = ('a, 'b) Base.Hashtbl.t
module Hashable = Hashtbl.Hashable
val hash : 'a -> int
val hash_param : int -> int -> 'a -> int
type ('a, 'b) t = ('a, 'b) Base.Hashtbl.t
val sexp_of_t : ('a -> Base__.Sexplib.Sexp.t) -> ('b -> Base__.Sexplib.Sexp.t) -> ('a, 'b) t -> Base__.Sexplib.Sexp.t
val invariant : 'a Base__.Invariant_intf.inv -> 'b Base__.Invariant_intf.inv -> ('a, 'b) t Base__.Invariant_intf.inv
type !'a key = 'a
val create : ('a key, 'b, unit -> ('a, 'b) t) Core_kernel__.Hashtbl_intf.Hashtbl_intf.create_options_with_first_class_module
val of_alist : ('a key, 'b, ('a key * 'b) list -> [ `Duplicate_key of 'a key | `Ok of ('a, 'b) t ]) Core_kernel__.Hashtbl_intf.Hashtbl_intf.create_options_with_first_class_module
val of_alist_report_all_dups : ('a key, 'b, ('a key * 'b) list -> [ `Duplicate_keys of 'a key list | `Ok of ('a, 'b) t ]) Core_kernel__.Hashtbl_intf.Hashtbl_intf.create_options_with_first_class_module
val of_alist_or_error : ('a key, 'b, ('a key * 'b) list -> ('a, 'b) t Base__.Or_error.t) Core_kernel__.Hashtbl_intf.Hashtbl_intf.create_options_with_first_class_module
val of_alist_exn : ('a key, 'b, ('a key * 'b) list -> ('a, 'b) t) Core_kernel__.Hashtbl_intf.Hashtbl_intf.create_options_with_first_class_module
val of_alist_multi : ('a key, 'b list, ('a key * 'b) list -> ('a, 'b list) t) Core_kernel__.Hashtbl_intf.Hashtbl_intf.create_options_with_first_class_module
val create_mapped : ('a key, 'b, get_key:('r -> 'a key) -> get_data:('r -> 'b) -> 'r list -> [ `Duplicate_keys of 'a key list | `Ok of ('a, 'b) t ]) Core_kernel__.Hashtbl_intf.Hashtbl_intf.create_options_with_first_class_module
val create_with_key : ('a key, 'r, get_key:('r -> 'a key) -> 'r list -> [ `Duplicate_keys of 'a key list | `Ok of ('a, 'r) t ]) Core_kernel__.Hashtbl_intf.Hashtbl_intf.create_options_with_first_class_module
val create_with_key_or_error : ('a key, 'r, get_key:('r -> 'a key) -> 'r list -> ('a, 'r) t Base__.Or_error.t) Core_kernel__.Hashtbl_intf.Hashtbl_intf.create_options_with_first_class_module
val create_with_key_exn : ('a key, 'r, get_key:('r -> 'a key) -> 'r list -> ('a, 'r) t) Core_kernel__.Hashtbl_intf.Hashtbl_intf.create_options_with_first_class_module
val group : ('a key, 'b, get_key:('r -> 'a key) -> get_data:('r -> 'b) -> combine:('b -> 'b -> 'b) -> 'r list -> ('a, 'b) t) Core_kernel__.Hashtbl_intf.Hashtbl_intf.create_options_with_first_class_module
val sexp_of_key : ('a, 'b) t -> 'a key -> Base__.Sexp.t
val clear : ('a, 'b) t -> unit
val copy : ('a, 'b) t -> ('a, 'b) t
val fold : ('a, 'b) t -> init:'c -> f:(key:'a key -> data:'b -> 'c -> 'c) -> 'c
val iter_keys : ('a, 'b) t -> f:('a key -> unit) -> unit
val iter : ('a, 'b) t -> f:('b -> unit) -> unit
val iteri : ('a, 'b) t -> f:(key:'a key -> data:'b -> unit) -> unit
val existsi : ('a, 'b) t -> f:(key:'a key -> data:'b -> bool) -> bool
val exists : ('a, 'b) t -> f:('b -> bool) -> bool
val for_alli : ('a, 'b) t -> f:(key:'a key -> data:'b -> bool) -> bool
val for_all : ('a, 'b) t -> f:('b -> bool) -> bool
val counti : ('a, 'b) t -> f:(key:'a key -> data:'b -> bool) -> int
val count : ('a, 'b) t -> f:('b -> bool) -> int
val length : ('a, 'b) t -> int
val is_empty : ('a, 'b) t -> bool
val mem : ('a, 'b) t -> 'a key -> bool
val remove : ('a, 'b) t -> 'a key -> unit
val set : ('a, 'b) t -> key:'a key -> data:'b -> unit
val add : ('a, 'b) t -> key:'a key -> data:'b -> [ `Duplicate | `Ok ]
val add_exn : ('a, 'b) t -> key:'a key -> data:'b -> unit
val change : ('a, 'b) t -> 'a key -> f:('b option -> 'b option) -> unit
val update : ('a, 'b) t -> 'a key -> f:('b option -> 'b) -> unit
val map : ('a, 'b) t -> f:('b -> 'c) -> ('a, 'c) t
val mapi : ('a, 'b) t -> f:(key:'a key -> data:'b -> 'c) -> ('a, 'c) t
val filter_map : ('a, 'b) t -> f:('b -> 'c option) -> ('a, 'c) t
val filter_mapi : ('a, 'b) t -> f:(key:'a key -> data:'b -> 'c option) -> ('a, 'c) t
val filter_keys : ('a, 'b) t -> f:('a key -> bool) -> ('a, 'b) t
val filter : ('a, 'b) t -> f:('b -> bool) -> ('a, 'b) t
val filteri : ('a, 'b) t -> f:(key:'a key -> data:'b -> bool) -> ('a, 'b) t
val partition_map : ('a, 'b) t -> f:('b -> [ `Fst of 'c | `Snd of 'd ]) -> ('a, 'c) t * ('a, 'd) t
val partition_mapi : ('a, 'b) t -> f:(key:'a key -> data:'b -> [ `Fst of 'c | `Snd of 'd ]) -> ('a, 'c) t * ('a, 'd) t
val partition_tf : ('a, 'b) t -> f:('b -> bool) -> ('a, 'b) t * ('a, 'b) t
val partitioni_tf : ('a, 'b) t -> f:(key:'a key -> data:'b -> bool) -> ('a, 'b) t * ('a, 'b) t
val find_or_add : ('a, 'b) t -> 'a key -> default:(unit -> 'b) -> 'b
val find : ('a, 'b) t -> 'a key -> 'b option
val find_exn : ('a, 'b) t -> 'a key -> 'b
val find_and_call : ('a, 'b) t -> 'a key -> if_found:('b -> 'c) -> if_not_found:('a key -> 'c) -> 'c
val find_and_remove : ('a, 'b) t -> 'a key -> 'b option
val merge : ('k, 'a) t -> ('k, 'b) t -> f: (key:'k key -> [ `Both of 'a * 'b | `Left of 'a | `Right of 'b ] -> 'c option) -> ('k, 'c) t
type !'a merge_into_action =
  1. | Remove
  2. | Set_to of 'a
val merge_into : src:('k, 'a) t -> dst:('k, 'b) t -> f:(key:'k key -> 'a -> 'b option -> 'b merge_into_action) -> unit
val keys : ('a, 'b) t -> 'a key list
val data : ('a, 'b) t -> 'b list
val filter_keys_inplace : ('a, 'b) t -> f:('a key -> bool) -> unit
val filter_inplace : ('a, 'b) t -> f:('b -> bool) -> unit
val filteri_inplace : ('a, 'b) t -> f:(key:'a key -> data:'b -> bool) -> unit
val map_inplace : ('a, 'b) t -> f:('b -> 'b) -> unit
val mapi_inplace : ('a, 'b) t -> f:(key:'a key -> data:'b -> 'b) -> unit
val filter_map_inplace : ('a, 'b) t -> f:('b -> 'b option) -> unit
val filter_mapi_inplace : ('a, 'b) t -> f:(key:'a key -> data:'b -> 'b option) -> unit
val equal : ('a, 'b) t -> ('a, 'b) t -> ('b -> 'b -> bool) -> bool
val similar : ('a, 'b1) t -> ('a, 'b2) t -> ('b1 -> 'b2 -> bool) -> bool
val to_alist : ('a, 'b) t -> ('a key * 'b) list
val validate : name:('a key -> string) -> 'b Base__.Validate.check -> ('a, 'b) t Base__.Validate.check
val incr : ?by:int -> ?remove_if_zero:bool -> ('a, int) t -> 'a key -> unit
val decr : ?by:int -> ?remove_if_zero:bool -> ('a, int) t -> 'a key -> unit
val add_multi : ('a, 'b list) t -> key:'a key -> data:'b -> unit
val remove_multi : ('a, 'b list) t -> 'a key -> unit
val find_multi : ('a, 'b list) t -> 'a key -> 'b list
val iter_vals : ('a, 'b) t -> f:('b -> unit) -> unit
  • deprecated [since 2016-04] Use iter instead
val replace : ('a, 'b) t -> key:'a key -> data:'b -> unit
  • deprecated [since 2015-10] Use set instead
val replace_all : ('a, 'b) t -> f:('b -> 'b) -> unit
  • deprecated [since 2016-02] Use map_inplace instead
val replace_alli : ('a, 'b) t -> f:(key:'a key -> data:'b -> 'b) -> unit
  • deprecated [since 2016-02] Use mapi_inplace instead
val filter_replace_all : ('a, 'b) t -> f:('b -> 'b option) -> unit
  • deprecated [since 2016-02] Use filter_map_inplace instead
val filter_replace_alli : ('a, 'b) t -> f:(key:'a key -> data:'b -> 'b option) -> unit
  • deprecated [since 2016-02] Use filter_mapi_inplace instead
val hashable : ('key, 'a) t -> 'key Hashable.t
module Using_hashable : sig ... end
module Poly : sig ... end
module type Key_plain = Hashtbl.Key_plain
module type Key = Hashtbl.Key
module type Key_binable = Hashtbl.Key_binable
module type S_plain = Hashtbl.S_plain
module type S = Hashtbl.S
module Make_plain (Key : Hashtbl.Key_plain) : sig ... end
module Make (Key : Hashtbl.Key) : sig ... end
module Make_binable (Key : Hashtbl.Key_binable) : sig ... end
OCaml

Innovation. Community. Security.