Add an argument to Sequence.persistent to choose initial chunk size.

This commit is contained in:
Drup 2014-05-20 23:00:17 +02:00
parent dcbee64684
commit e4691be2a5
2 changed files with 18 additions and 12 deletions

View file

@ -149,9 +149,9 @@ module MList = struct
| Cons of 'a array * int ref * 'a node ref | Cons of 'a array * int ref * 'a node ref
(* build and call callback on every element *) (* 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 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 *) (* fill the list. prev: tail-reference from previous node *)
let prev, cur = ref start, ref Nil in let prev, cur = ref start, ref Nil in
seq seq
@ -175,8 +175,8 @@ module MList = struct
!prev := !cur; !prev := !cur;
!start !start
let of_seq seq = let of_seq ?init_size seq =
of_seq_with seq (fun _ -> ()) of_seq_with seq ?init_size (fun _ -> ())
let is_empty = function let is_empty = function
| Nil -> true | Nil -> true
@ -239,22 +239,22 @@ end
(** Iterate on the sequence, storing elements in a data structure. (** Iterate on the sequence, storing elements in a data structure.
The resulting sequence can be iterated on as many times as needed. *) The resulting sequence can be iterated on as many times as needed. *)
let persistent seq = let persistent ?init_size seq =
let l = MList.of_seq seq in let l = MList.of_seq ?init_size seq in
MList.to_seq l MList.to_seq l
type 'a lazy_state = type 'a lazy_state =
| LazySuspend | LazySuspend
| LazyCached of 'a t | LazyCached of 'a t
let persistent_lazy (seq:'a t) = let persistent_lazy ?init_size (seq:'a t) =
let r = ref LazySuspend in let r = ref LazySuspend in
fun k -> fun k ->
match !r with match !r with
| LazyCached seq' -> seq' k | LazyCached seq' -> seq' k
| LazySuspend -> | LazySuspend ->
(* here if this traversal is interruted, no caching occurs *) (* 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') r := LazyCached (MList.to_seq seq')
(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. *) (** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. *)

View file

@ -151,13 +151,16 @@ val fmap : ('a -> 'b option) -> 'a t -> 'b t
val intersperse : 'a -> 'a t -> 'a t val intersperse : 'a -> 'a t -> 'a t
(** Insert the single element between every element of the sequence *) (** 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. (** Iterate on the sequence, storing elements in a data structure.
The resulting sequence can be iterated on as many times as needed. The resulting sequence can be iterated on as many times as needed.
{b Note}: calling persistent on an already persistent sequence {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], (** Lazy version of {!persistent}. When calling [persistent_lazy s],
a new sequence [s'] is immediately returned (without actually consuming a new sequence [s'] is immediately returned (without actually consuming
[s]) in constant time; the first time [s'] is iterated on, [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 {b warning}: on the first traversal of [s'], if the traversal
is interrupted prematurely ({!take}, etc.) then [s'] will not be 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 val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time. (** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time.