diff --git a/sequence.ml b/sequence.ml index 6d7887e..1ad632f 100644 --- a/sequence.ml +++ b/sequence.ml @@ -82,9 +82,11 @@ let concat s = (** Take at most [n] elements from the sequence *) let take n seq = let count = ref 0 in - let seq_fun k = seq.seq_fun - (fun x -> - if !count < n then begin incr count; k x end) + let seq_fun k = + try + seq.seq_fun + (fun x -> if !count < n then begin incr count; k x end else raise Exit) + with Exit -> () in { seq_fun; } (** Drop the [n] first elements of the sequence *) @@ -125,15 +127,54 @@ let exists p seq = module List = struct let of_seq seq = List.rev (fold (fun y x -> x::y) [] seq) + let to_seq l = from_iter (fun k -> List.iter k l) end +module Array = + struct + let of_seq seq = + (* intermediate list... *) + let l = List.of_seq seq in + Array.of_list l + + let to_seq a = from_iter (fun k -> Array.iter k a) + + let slice a i j = + assert (i >= 0 && j < Array.length a); + let seq_fun k = + for idx = i to j do + k a.(idx); (* iterate on sub-array *) + done + in { seq_fun; } + end + +module Stack = + struct + let push_seq s seq = iter (fun x -> Stack.push x s) seq + + let to_seq s = from_iter (fun k -> Stack.iter k s) + end + +module Queue = + struct + let push_seq q seq = iter (fun x -> Queue.push x q) seq + let to_seq q = from_iter (fun k -> Queue.iter k q) + end + module Hashtbl = struct + let add_seq h seq = + iter (fun (k,v) -> Hashtbl.add h k v) seq + + let replace_seq h seq = + iter (fun (k,v) -> Hashtbl.replace h k v) seq + let of_seq seq = let h = Hashtbl.create 3 in - iter (fun (k,v) -> Hashtbl.replace h k v) seq; + replace_seq h seq; h + let to_seq h = from_iter (fun k -> Hashtbl.iter (fun a b -> k (a, b)) h) end @@ -144,6 +185,10 @@ module Int = let seq_fun k = for i = start to stop do k i done in { seq_fun; } + + let repeat i = + let seq_fun k = while true do k i; done in + { seq_fun; } end module Set = diff --git a/sequence.mli b/sequence.mli index ba551fc..e8396bc 100644 --- a/sequence.mli +++ b/sequence.mli @@ -23,10 +23,13 @@ for any direct, indirect, incidental, special, exemplary, or consequential of this software, even if advised of the possibility of such damage. *) -(** {2 Transient iterators, that abstract on a finite sequence of elements.} *) +(** Transient iterators, that abstract on a finite sequence of elements. They + are designed to allow easy transfer (mappings) between data structures, + without defining n^2 conversions between the n types. *) type 'a t - (** Sequence abstract iterator type *) + (** Sequence abstract iterator type, representing a finite sequence of + values of type ['a]. *) (** {2 Build a sequence} *) @@ -36,7 +39,7 @@ val from_iter : (('a -> unit) -> unit) -> 'a t val singleton : 'a -> 'a t (** Singleton sequence *) -(** {2 Use a sequence} *) +(** {2 Consume a sequence} *) val iter : ('a -> unit) -> 'a t -> unit (** Consume the sequence, passing all its arguments to the function *) @@ -50,6 +53,14 @@ val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b val map : ('a -> 'b) -> 'a t -> 'b t (** Map objects of the sequence into other elements, lazily *) +val for_all : ('a -> bool) -> 'a t -> bool + (** Do all elements satisfy the predicate? *) + +val exists : ('a -> bool) -> 'a t -> bool + (** Exists there some element satisfying the predicate? *) + +(** {2 Transform a sequence} *) + val filter : ('a -> bool) -> 'a t -> 'a t (** Filter on elements of the sequence *) @@ -68,31 +79,71 @@ val drop : int -> 'a t -> 'a t val rev : 'a t -> 'a t (** Reverse the sequence. O(n) memory. *) -val for_all : ('a -> bool) -> 'a t -> bool - (** Do all elements satisfy the predicate? *) - -val exists : ('a -> bool) -> 'a t -> bool - (** Exists there some element satisfying the predicate? *) - (** {2 Basic data structures converters} *) module List : sig val of_seq : 'a t -> 'a list + val to_seq : 'a list -> 'a t end +module Array : + sig + val of_seq : 'a t -> 'a array + + val to_seq : 'a array -> 'a t + + val slice : 'a array -> int -> int -> 'a t + (** [slice a i j] Sequence of elements whose indexes range + from [i] to [j] *) + end + +module Stack : + sig + val push_seq : 'a Stack.t -> 'a t -> unit + (** Push elements of the sequence on the stack *) + + val to_seq : 'a Stack.t -> 'a t + (** Sequence of elements of the stack (same order as [Stack.iter]) *) + end + +module Queue : + sig + val push_seq : 'a Queue.t -> 'a t -> unit + (** Push elements of the sequence into the queue *) + + val to_seq : 'a Queue.t -> 'a t + (** Sequence of elements contained in the queue, FIFO order *) + end + module Hashtbl : sig + val add_seq : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit + (** Add elements of the sequence to the hashtable, with + Hashtbl.add *) + + val replace_seq : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit + (** Add elements of the sequence to the hashtable, with + Hashtbl.replace (erases conflicting bindings) *) + val of_seq : ('a * 'b) t -> ('a, 'b) Hashtbl.t + (** Build a hashtable from a sequence *) + val to_seq : ('a, 'b) Hashtbl.t -> ('a * 'b) t + (** Sequence of key/value pairs from the hashtable *) end -(** Iterate on ranges of ints *) +(** Sequences of ints *) module Int : sig val range : start:int -> stop:int -> int t (** Iterator on [start...stop] by steps 1 *) + + val repeat : int -> int t + (** Infinite sequence of integers. Should be used only with + transformers such as [take], that work even with infinite + sequences. *) end (** Iterate on sets. The Set module has to be provided. *)