From 8efc421650c0858b52195a5e0ef8b7b9ab6b7487 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Mon, 18 Mar 2013 23:12:57 +0100 Subject: [PATCH] draft of Enum type (restartable generator a la Batteries) --- containers.mllib | 1 + enum.ml | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ enum.mli | 69 +++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 enum.ml create mode 100644 enum.mli diff --git a/containers.mllib b/containers.mllib index 4a7c1c1a..957ef6e0 100644 --- a/containers.mllib +++ b/containers.mllib @@ -1,5 +1,6 @@ Vector Deque +Enum Graph Cache FlatHashtbl diff --git a/enum.ml b/enum.ml new file mode 100644 index 00000000..080b276c --- /dev/null +++ b/enum.ml @@ -0,0 +1,94 @@ +(* +Copyright (c) 2013, 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 Consumable generators} *) + +exception EOG + (** End of Generation *) + +type 'a t = unit -> 'a generator + (** An enum is a generator of generators *) +and 'a generator = unit -> 'a + (** A generator may be called several times, yielding the next value + each time. It raises EOG when it reaches the end. *) + +let start enum = enum () + +let next gen = gen () + +let junk gen = ignore (gen ()) + +let fold f acc enum = + let rec fold acc gen = + let acc', stop = + try f acc (gen ()), true + with EOG -> acc, false in + if stop then acc' else fold acc' gen + in + fold acc (enum ()) + +let iter f enum = + let rec iter gen = + let stop = + try f (gen ()); true + with EOG -> false in + if stop then () else iter gen + in + iter (enum ()) + +let length enum = + fold (fun acc _ -> acc + 1) 0 enum + +let map f enum = + (* another enum *) + fun () -> + let gen = enum () in + (* the mapped generator *) + fun () -> + try f (gen ()) + with EOG -> raise EOG + +let of_list l = + fun () -> + let l = ref l in + fun () -> + match !l with + | [] -> raise EOG + | x::l' -> l := l'; x + +let to_list enum = + let rec fold gen = + try (gen ()) :: fold gen + with EOG -> [] + in fold (enum ()) + +let to_rev_list enum = + let rec fold acc gen = + let acc', stop = + try gen () :: acc, true + with EOG -> acc, false + in if stop then acc' else fold acc' gen + in + fold [] (enum ()) diff --git a/enum.mli b/enum.mli new file mode 100644 index 00000000..b4200f9e --- /dev/null +++ b/enum.mli @@ -0,0 +1,69 @@ +(* +Copyright (c) 2013, 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 Consumable generators} *) + +(** This structure is inspired from Ocaml Batteries' BatEnum.t. It features + restartable generators. *) + +exception EOG + (** End of Generation *) + +type 'a t = unit -> 'a generator + (** An enum is a generator of generators *) +and 'a generator = unit -> 'a + (** A generator may be called several times, yielding the next value + each time. It raises EOG when it reaches the end. *) + +val start : 'a t -> 'a generator + (** Create a new generator *) + +val next : 'a generator -> 'a + (** Get next element, or raise EOG *) + +val junk : 'a generator -> unit + (** Drop element *) + +val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b + (** Fold on the generator *) + +val iter : ('a -> unit) -> 'a t -> unit + (** Iterate on the enum *) + +val length : _ t -> int + (** Length of an enum (linear time) *) + +val map : ('a -> 'b) -> 'a t -> 'b t + (** Lazy map *) + +val of_list : 'a list -> 'a t + (** Enumerate the list *) + +val to_list : 'a t -> 'a list + (** non tail-call trasnformation to list *) + +val to_rev_list : 'a t -> 'a list + (** Tail call conversion to list, in reverse order *) +