more lightweight representation of sequences (no record, just a function)

This commit is contained in:
Simon Cruanes 2013-02-04 20:41:47 +01:00
parent c4b7885e2a
commit ab74acf87a

View file

@ -26,21 +26,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
(** {2 Transient iterators, that abstract on a finite sequence of elements. *) (** {2 Transient iterators, that abstract on a finite sequence of elements. *)
(** Sequence abstract iterator type *) (** Sequence abstract iterator type *)
type 'a t = { type 'a t = ('a -> unit) -> unit
seq_fun: ('a -> unit) -> unit;
}
(** Build a sequence from a iter function *) (** Build a sequence from a iter function *)
let from_iter f = { let from_iter f = f
seq_fun = f;
}
let singleton x = { let singleton x = fun k -> k x
seq_fun = fun k -> k x;
}
(** Consume the sequence, passing all its arguments to the function *) (** Consume the sequence, passing all its arguments to the function *)
let iter f seq = seq.seq_fun f let iter f seq = seq f
(** Iterate on elements and their index in the sequence *) (** Iterate on elements and their index in the sequence *)
let iteri f seq = let iteri f seq =
@ -48,57 +42,54 @@ let iteri f seq =
let k x = let k x =
f !r x; f !r x;
incr r incr r
in seq.seq_fun k in seq k
(** Fold over elements of the sequence, consuming it *) (** Fold over elements of the sequence, consuming it *)
let fold f init seq = let fold f init seq =
let r = ref init in let r = ref init in
seq.seq_fun (fun elt -> r := f !r elt); seq (fun elt -> r := f !r elt);
!r !r
(** Map objects of the sequence into other elements, lazily *) (** Map objects of the sequence into other elements, lazily *)
let map f seq = let map f seq =
let seq_fun' k = seq.seq_fun (fun x -> k (f x)) in let seq_fun' k = seq (fun x -> k (f x)) in
{ seq_fun=seq_fun'; } seq_fun'
(** Filter on elements of the sequence *) (** Filter on elements of the sequence *)
let filter p seq = let filter p seq =
let seq_fun' k = seq.seq_fun (fun x -> if p x then k x) in let seq_fun' k = seq (fun x -> if p x then k x) in
{ seq_fun=seq_fun'; } seq_fun'
(** Append two sequences *) (** Append two sequences *)
let append s1 s2 = let append s1 s2 =
let seq_fun k = s1.seq_fun k; s2.seq_fun k in let seq_fun k = s1 k; s2 k in
{ seq_fun; } seq_fun
(** Concatenate a sequence of sequences into one sequence *) (** Concatenate a sequence of sequences into one sequence *)
let concat s = let concat s =
let seq_fun k = fun k ->
(* function that is called on every sub-sequence *) (* function that is called on every sub-sequence *)
let k_seq seq = iter k seq in let k_seq seq = iter k seq in
s.seq_fun k_seq s k_seq
in { seq_fun; }
(** Take at most [n] elements from the sequence *) (** Take at most [n] elements from the sequence *)
let take n seq = let take n seq =
let count = ref 0 in let count = ref 0 in
let seq_fun k = fun k ->
try try
seq.seq_fun seq
(fun x -> if !count < n then begin incr count; k x end else raise Exit) (fun x -> if !count < n then begin incr count; k x end else raise Exit)
with Exit -> () with Exit -> ()
in { seq_fun; }
(** Drop the [n] first elements of the sequence *) (** Drop the [n] first elements of the sequence *)
let drop n seq = let drop n seq =
let count = ref 0 in let count = ref 0 in
let seq_fun k = seq.seq_fun fun k -> seq
(fun x -> if !count >= n then k x else incr count) (fun x -> if !count >= n then k x else incr count)
in { seq_fun; }
(** Reverse the sequence. O(n) memory. *) (** Reverse the sequence. O(n) memory. *)
let rev seq = let rev seq =
let seq_fun k = fun k ->
(* if we have traversed [s_1, ..., s_m], [cont ()] will call [k] on s_m, (* if we have traversed [s_1, ..., s_m], [cont ()] will call [k] on s_m,
s_{m-1}, ..., s_1. Once we know [s_{m+1}], we update [cont] so that it s_{m-1}, ..., s_1. Once we know [s_{m+1}], we update [cont] so that it
first returns it, and then called the previous cont. *) first returns it, and then called the previous cont. *)
@ -108,19 +99,18 @@ let rev seq =
let cont' () = k x; current_cont () in let cont' () = k x; current_cont () in
cont := cont') seq; cont := cont') seq;
!cont () !cont ()
in { seq_fun; }
(** Do all elements satisfy the predicate? *) (** Do all elements satisfy the predicate? *)
let for_all p seq = let for_all p seq =
try try
seq.seq_fun (fun x -> if not (p x) then raise Exit); seq (fun x -> if not (p x) then raise Exit);
true true
with Exit -> false with Exit -> false
(** Exists there some element satisfying the predicate? *) (** Exists there some element satisfying the predicate? *)
let exists p seq = let exists p seq =
try try
seq.seq_fun (fun x -> if p x then raise Exit); seq (fun x -> if p x then raise Exit);
false false
with Exit -> true with Exit -> true
@ -152,11 +142,10 @@ module Array =
let slice a i j = let slice a i j =
assert (i >= 0 && j < Array.length a); assert (i >= 0 && j < Array.length a);
let seq_fun k = fun k ->
for idx = i to j do for idx = i to j do
k a.(idx); (* iterate on sub-array *) k a.(idx); (* iterate on sub-array *)
done done
in { seq_fun; }
end end
module Stack = module Stack =
@ -208,13 +197,10 @@ module String =
module Int = module Int =
struct struct
let range ~start ~stop = let range ~start ~stop =
let seq_fun k = fun k ->
for i = start to stop do k i done for i = start to stop do k i done
in { seq_fun; }
let repeat i = let repeat i = fun k -> while true do k i; done
let seq_fun k = while true do k i; done in
{ seq_fun; }
end end
(** Iterate on sets. The functor must be instantiated with a set type *) (** Iterate on sets. The functor must be instantiated with a set type *)