diff --git a/README.md b/README.md index de8f5e25..040b163c 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,7 @@ Documentation [here](http://cedeela.fr/~simon/software/containers). - `CCFQueue`, a purely functional double-ended queue structure - `CCBV`, mutable bitvectors - `CCPersistentHashtbl`, a semi-persistent hashtable (similar to [persistent arrays](https://www.lri.fr/~filliatr/ftp/ocaml/ds/parray.ml.html)) +- `CCMixmap`, `CCMixtbl`, `CCMixset`, containers of universal types (heterogenous containers) ### Containers.io diff --git a/_oasis b/_oasis index 9d5c8663..568502b7 100644 --- a/_oasis +++ b/_oasis @@ -82,7 +82,8 @@ Library "containers_data" Path: src/data Modules: CCMultiMap, CCMultiSet, CCTrie, CCFlatHashtbl, CCCache, CCPersistentHashtbl, CCDeque, CCFQueue, CCBV, CCMixtbl, - CCMixmap, CCRingBuffer, CCIntMap, CCPersistentArray + CCMixmap, CCRingBuffer, CCIntMap, CCPersistentArray, + CCMixset BuildDepends: bytes FindlibParent: containers FindlibName: data diff --git a/doc/intro.txt b/doc/intro.txt index 42f0f3c6..5b68eb1f 100644 --- a/doc/intro.txt +++ b/doc/intro.txt @@ -68,6 +68,7 @@ CCFQueue CCFlatHashtbl CCIntMap CCMixmap +CCMixset CCMixtbl CCMultiMap CCMultiSet diff --git a/src/data/CCMixset.ml b/src/data/CCMixset.ml new file mode 100644 index 00000000..f847d3a6 --- /dev/null +++ b/src/data/CCMixset.ml @@ -0,0 +1,77 @@ + +(* +copyright (c) 2013-2015, simon cruanes +all rights reserved. + +redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. redistributions in binary +form must reproduce the above copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other materials provided with +the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*) + +(** {1 Set of Heterogeneous Values} *) + +module IMap = Map.Make(struct + type t = int + let compare : int -> int -> int = compare +end) + +(*$R + let k1 : int key = newkey () in + let k2 : int key = newkey () in + let k3 : string key = newkey () in + let set = + empty + |> set ~key:k1 1 + |> set ~key:k2 2 + |> set ~key:k3 "3" + in + assert (get ~key:k1 set = Some 1); + assert (get ~key:k2 set = Some 2); + assert (get ~key:k3 set = Some "3"); + () +*) + +type t = (unit -> unit) IMap.t +and 'a key = { + id: int; + mutable opt : 'a option; +};; + +let newkey_n_ = ref 0 + +let newkey () = + let id = !newkey_n_ in + incr newkey_n_; + { id; opt=None; } + +let empty = IMap.empty + +let get ~key set = + key.opt <- None; + try + (IMap.find key.id set) (); + key.opt + with Not_found -> None + +let get_exn ~key set = match get ~key set with + | None -> raise Not_found + | Some v -> v + +let set ~key v set = + IMap.add key.id (fun () -> key.opt <- Some v) set diff --git a/src/data/CCMixset.mli b/src/data/CCMixset.mli new file mode 100644 index 00000000..23412a06 --- /dev/null +++ b/src/data/CCMixset.mli @@ -0,0 +1,65 @@ + +(* +copyright (c) 2013-2015, simon cruanes +all rights reserved. + +redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. redistributions in binary +form must reproduce the above copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other materials provided with +the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*) + +(** {1 Set of Heterogeneous Values} + + {[ + let k1 : int key = newkey () in + let k2 : int key = newkey () in + let k3 : string key = newkey () in + let set = + empty + |> set ~key:k1 1 + |> set ~key:k2 2 + |> set ~key:k3 "3" + in + assert (get ~key:k1 set = Some 1); + assert (get ~key:k2 set = Some 2); + assert (get ~key:k3 set = Some "3"); + () + ]} + + @since NEXT_RELEASE *) + +type t +(** A set of values of heterogeneous types *) + +type 'a key +(** A unique "key" to access a value of type ['a] in a [set] *) + +val newkey : unit -> 'a key +(** [newkey ()] creates a new unique key that can be used to access + a ['a] value in a set *) + +val empty : t + +val set : key:'a key -> 'a -> t -> t + +val get : key:'a key -> t -> 'a option + +val get_exn : key:'a key -> t -> 'a +(** Same as {!get}, but can fail + @raise Not_found if the key is not present *)