diff --git a/sequence.ml b/sequence.ml index 893f6c7..5a87c67 100644 --- a/sequence.ml +++ b/sequence.ml @@ -149,9 +149,9 @@ module MList = struct | Cons of 'a array * int ref * 'a node ref (* build and call callback on every element *) - let of_seq_with seq k = + let of_seq_with ?(init_size=8) seq k = let start = ref Nil in - let chunk_size = ref 8 in + let chunk_size = ref init_size in (* fill the list. prev: tail-reference from previous node *) let prev, cur = ref start, ref Nil in seq @@ -175,8 +175,8 @@ module MList = struct !prev := !cur; !start - let of_seq seq = - of_seq_with seq (fun _ -> ()) + let of_seq ?init_size seq = + of_seq_with seq ?init_size (fun _ -> ()) let is_empty = function | Nil -> true @@ -239,22 +239,22 @@ end (** Iterate on the sequence, storing elements in a data structure. The resulting sequence can be iterated on as many times as needed. *) -let persistent seq = - let l = MList.of_seq seq in +let persistent ?init_size seq = + let l = MList.of_seq ?init_size seq in MList.to_seq l type 'a lazy_state = | LazySuspend | LazyCached of 'a t -let persistent_lazy (seq:'a t) = +let persistent_lazy ?init_size (seq:'a t) = let r = ref LazySuspend in fun k -> match !r with | LazyCached seq' -> seq' k | LazySuspend -> (* here if this traversal is interruted, no caching occurs *) - let seq' = MList.of_seq_with seq k in + let seq' = MList.of_seq_with ?init_size seq k in r := LazyCached (MList.to_seq seq') (** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. *) @@ -686,7 +686,7 @@ include Infix let pp_seq ?(sep=", ") pp_elt formatter seq = let first = ref true in iter - (fun x -> + (fun x -> (if !first then first := false else begin Format.pp_print_string formatter sep; @@ -698,7 +698,7 @@ let pp_seq ?(sep=", ") pp_elt formatter seq = let pp_buf ?(sep=", ") pp_elt buf seq = let first = ref true in iter - (fun x -> + (fun x -> if !first then first := false else Buffer.add_string buf sep; pp_elt buf x) seq diff --git a/sequence.mli b/sequence.mli index 39444ee..5ce7409 100644 --- a/sequence.mli +++ b/sequence.mli @@ -32,7 +32,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. of many combinators. However, for transient iterators, the {!persistent} function is provided, storing elements of a transient iterator in memory; the iterator can then be used several times (See further). - + Note that some combinators also return sequences (e.g. {!group}). The transformation is computed on the fly every time one iterates over the resulting sequence. If a transformation performs heavy computation, @@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. until their result is iterated on. For instance, if one calls {!map} on a sequence, one gets a new sequence, but nothing else happens until this new sequence is used (by folding or iterating on it). - + If a sequence is built from an iteration function that is {b repeatable} (i.e. calling it several times always iterates on the same set of elements, for instance List.iter or Map.iter), then @@ -151,13 +151,16 @@ val fmap : ('a -> 'b option) -> 'a t -> 'b t val intersperse : 'a -> 'a t -> 'a t (** Insert the single element between every element of the sequence *) -val persistent : 'a t -> 'a t +val persistent : ?init_size:int -> 'a t -> 'a t (** Iterate on the sequence, storing elements in a data structure. The resulting sequence can be iterated on as many times as needed. {b Note}: calling persistent on an already persistent sequence - will still make a new copy of the sequence! *) + will still make a new copy of the sequence! -val persistent_lazy : 'a t -> 'a t + The optional argument [init_size] control the initial size of the underlying data structure. For very small sequences, it is more efficient to have [init_size] bigger than the length of your sequence. + *) + +val persistent_lazy : ?init_size:int -> 'a t -> 'a t (** Lazy version of {!persistent}. When calling [persistent_lazy s], a new sequence [s'] is immediately returned (without actually consuming [s]) in constant time; the first time [s'] is iterated on, @@ -166,7 +169,10 @@ val persistent_lazy : 'a t -> 'a t {b warning}: on the first traversal of [s'], if the traversal is interrupted prematurely ({!take}, etc.) then [s'] will not be - memorized, and the next call to [s'] will traverse [s] again. *) + memorized, and the next call to [s'] will traverse [s] again. + + The optional argument [init_size] control the initial size of the underlying data structure. For very small sequences, it is more efficient to have [init_size] bigger than the length of your sequence. + *) val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t (** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. @@ -194,7 +200,7 @@ val join : join_row:('a -> 'b -> 'c option) -> 'a t -> 'b t -> 'c t the two elements do not combine. Assume that [b] allows for multiple iterations. *) -val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t +val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t (** [unfoldr f b] will apply [f] to [b]. If it yields [Some (x,b')] then [x] is returned and unfoldr recurses with [b']. *) @@ -359,7 +365,7 @@ module Set : sig (** Create an enriched Set module from the given one *) module Adapt(X : Set.S) : S with type elt = X.elt and type t = X.t - + (** Functor to build an extended Set module from an ordered type *) module Make(X : Set.OrderedType) : S with type elt = X.t end