mirror of
https://github.com/c-cube/iter.git
synced 2025-12-06 11:15:32 -05:00
Sequence.persistent_lazy added, for caching without upfront cost
This commit is contained in:
parent
7464ba2488
commit
6ff605ac04
2 changed files with 31 additions and 2 deletions
22
sequence.ml
22
sequence.ml
|
|
@ -148,13 +148,16 @@ module MList = struct
|
||||||
| Nil
|
| Nil
|
||||||
| Cons of 'a array * int ref * 'a node ref
|
| Cons of 'a array * int ref * 'a node ref
|
||||||
|
|
||||||
let of_seq seq =
|
(* build and call callback on every element *)
|
||||||
|
let of_seq_with seq k =
|
||||||
let start = ref Nil in
|
let start = ref Nil in
|
||||||
let chunk_size = ref 8 in
|
let chunk_size = ref 8 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
|
||||||
(fun x -> match !cur with
|
(fun x ->
|
||||||
|
k x; (* callback *)
|
||||||
|
match !cur with
|
||||||
| Nil ->
|
| Nil ->
|
||||||
let n = !chunk_size in
|
let n = !chunk_size in
|
||||||
if n < 4096 then chunk_size := 2 * !chunk_size;
|
if n < 4096 then chunk_size := 2 * !chunk_size;
|
||||||
|
|
@ -172,6 +175,9 @@ module MList = struct
|
||||||
!prev := !cur;
|
!prev := !cur;
|
||||||
!start
|
!start
|
||||||
|
|
||||||
|
let of_seq seq =
|
||||||
|
of_seq_with seq (fun _ -> ())
|
||||||
|
|
||||||
let is_empty = function
|
let is_empty = function
|
||||||
| Nil -> true
|
| Nil -> true
|
||||||
| Cons _ -> false
|
| Cons _ -> false
|
||||||
|
|
@ -237,6 +243,18 @@ let persistent seq =
|
||||||
let l = MList.of_seq seq in
|
let l = MList.of_seq seq in
|
||||||
MList.to_seq l
|
MList.to_seq l
|
||||||
|
|
||||||
|
type 'a lazy_seq = [`Suspend | `Cached of 'a t] ref
|
||||||
|
|
||||||
|
let persistent_lazy (seq:'a t) =
|
||||||
|
let (r:'a lazy_seq) = ref `Suspend in
|
||||||
|
fun k ->
|
||||||
|
match !r with
|
||||||
|
| `Cached seq' -> seq' k
|
||||||
|
| `Suspend ->
|
||||||
|
(* here if this traversal is interruted, no caching occurs *)
|
||||||
|
let seq' = MList.of_seq_with seq k in
|
||||||
|
r := `Cached (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. *)
|
||||||
let sort ?(cmp=Pervasives.compare) seq =
|
let sort ?(cmp=Pervasives.compare) seq =
|
||||||
(* use an intermediate list, then sort the list *)
|
(* use an intermediate list, then sort the list *)
|
||||||
|
|
|
||||||
11
sequence.mli
11
sequence.mli
|
|
@ -157,6 +157,17 @@ val persistent : 'a t -> 'a t
|
||||||
{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
|
||||||
|
(** 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,
|
||||||
|
it also consumes [s] and caches its content into a inner data
|
||||||
|
structure that will back [s'] for future iterations.
|
||||||
|
|
||||||
|
{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. *)
|
||||||
|
|
||||||
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.
|
||||||
It iterates on elements of the argument sequence immediately,
|
It iterates on elements of the argument sequence immediately,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue