diff --git a/sequence.ml b/sequence.ml index 4b9a0ae..869fe24 100644 --- a/sequence.ml +++ b/sequence.ml @@ -55,12 +55,28 @@ let fold f init seq = let r = ref init in seq (fun elt -> r := f !r elt); !r + +(** Fold over elements of the sequence and their index, consuming it *) +let foldi f init seq = + let i = ref 0 in + let r = ref init in + seq (fun elt -> + r := f !r !i elt; + incr i); + !r (** Map objects of the sequence into other elements, lazily *) let map f seq = let seq_fun' k = seq (fun x -> k (f x)) in seq_fun' +(** Map objects, along with their index in the sequence *) +let mapi f seq = + let seq_fun' k = + let i = ref 0 in + seq (fun x -> k (f !i x); incr i) in + seq_fun' + (** Filter on elements of the sequence *) let filter p seq = let seq_fun' k = seq (fun x -> if p x then k x) in @@ -156,6 +172,11 @@ let to_array seq = let of_array a = from_iter (fun k -> Array.iter k a) +let of_array_i a = + let seq k = + for i = 0 to Array.length a - 1 do k (i, a.(i)) done + in from_iter seq + (** [array_slice a i j] Sequence of elements whose indexes range from [i] to [j] *) let array_slice a i j = @@ -165,6 +186,11 @@ let array_slice a i j = k a.(idx); (* iterate on sub-array *) done +(** Sequence of elements of a stream *) +let of_stream s = + let seq k = Stream.iter k s in + from_iter seq + (** Push elements of the sequence on the stack *) let to_stack s seq = iter (fun x -> Stack.push x s) seq @@ -210,6 +236,10 @@ let of_in_channel ic = let c = input_char ic in k c done with End_of_file -> ()) +(** Copy content of the sequence into the buffer *) +let to_buffer seq buf = + iter (fun c -> Buffer.add_char buf c) seq + (** Iterator on integers in [start...stop] by steps 1 *) let int_range ~start ~stop = fun k -> diff --git a/sequence.mli b/sequence.mli index e7ee7ff..bc7267f 100644 --- a/sequence.mli +++ b/sequence.mli @@ -27,7 +27,7 @@ for any direct, indirect, incidental, special, exemplary, or consequential are designed to allow easy transfer (mappings) between data structures, without defining n^2 conversions between the n types. *) -type 'a t +type +'a t (** Sequence abstract iterator type, representing a finite sequence of values of type ['a]. *) @@ -57,9 +57,15 @@ val iteri : (int -> 'a -> unit) -> 'a t -> unit val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b (** Fold over elements of the sequence, consuming it *) +val foldi : ('b -> int -> 'a -> 'b) -> 'b -> 'a t -> 'b + (** Fold over elements of the sequence and their index, consuming it *) + val map : ('a -> 'b) -> 'a t -> 'b t (** Map objects of the sequence into other elements, lazily *) +val mapi : (int -> 'a -> 'b) -> 'a t -> 'b t + (** Map objects, along with their index in the sequence *) + val for_all : ('a -> bool) -> 'a t -> bool (** Do all elements satisfy the predicate? *) @@ -90,7 +96,7 @@ val drop : int -> 'a t -> 'a t (** Drop the [n] first elements of the sequence *) val rev : 'a t -> 'a t - (** Reverse the sequence. O(n) memory. *) + (** Reverse the sequence. O(n) memory and time. *) (** {2 Basic data structures converters} *) @@ -102,13 +108,21 @@ val to_rev_list : 'a t -> 'a list val of_list : 'a list -> 'a t val to_array : 'a t -> 'a array + (** Convert to an array. Currently not very efficient because + and intermediate list is used. *) val of_array : 'a array -> 'a t +val of_array_i : 'a array -> (int * 'a) t + (** Elements of the array, with their index *) + val array_slice : 'a array -> int -> int -> 'a t (** [array_slice a i j] Sequence of elements whose indexes range from [i] to [j] *) +val of_stream : 'a Stream.t -> 'a t + (** Sequence of elements of a stream *) + val to_stack : 'a Stack.t -> 'a t -> unit (** Push elements of the sequence on the stack *) @@ -142,6 +156,9 @@ val of_str : string -> char t val to_str : char t -> string val of_in_channel : in_channel -> char t +val to_buffer : char t -> Buffer.t -> unit + (** Copy content of the sequence into the buffer *) + val int_range : start:int -> stop:int -> int t (** Iterator on integers in [start...stop] by steps 1 *)