mirror of
https://github.com/c-cube/iter.git
synced 2025-12-06 11:15:32 -05:00
version 0.5.5
This commit is contained in:
commit
55e70d1950
16 changed files with 709 additions and 55 deletions
16
CHANGELOG.md
16
CHANGELOG.md
|
|
@ -1,5 +1,13 @@
|
|||
# Changelog
|
||||
|
||||
## 0.5.5
|
||||
|
||||
- new module `SequenceLabels`
|
||||
- `fold_while` fun
|
||||
- implement `Set.Adapt.of_list` for `< 4.02`
|
||||
- removed many warnings, fix tests
|
||||
- change name of `IO` functions (keep compat)
|
||||
|
||||
## 0.5.4
|
||||
|
||||
- depend on `bytes`
|
||||
|
|
@ -40,7 +48,7 @@
|
|||
## 0.4.1
|
||||
|
||||
- `persistent_lazy`
|
||||
- use bin_annot
|
||||
- use `bin_annot`
|
||||
|
||||
## 0.4
|
||||
|
||||
|
|
@ -82,4 +90,10 @@
|
|||
- `zip`, `unzip` and `zip_i` to convert between `t` and `t2`
|
||||
- added `scan` combinator
|
||||
|
||||
<<<<<<< HEAD
|
||||
note: git log --no-merges --pretty=%s previous_version..HEAD
|
||||
||||||| merged common ancestors
|
||||
note: git log --no-merges previous_version..HEAD --pretty=%s
|
||||
=======
|
||||
note: `git log --no-merges previous_version..HEAD --pretty=%s`
|
||||
>>>>>>> master
|
||||
|
|
|
|||
8
META
8
META
|
|
@ -1,6 +1,6 @@
|
|||
# OASIS_START
|
||||
# DO NOT EDIT (digest: 0c501104bbf1dfc40db58200fdbfdd57)
|
||||
version = "0.5.4"
|
||||
# DO NOT EDIT (digest: 2f8e4d7fc3cb814610643e4ca5e33697)
|
||||
version = "0.5.5"
|
||||
description = "Simple sequence (iterator) datatype and combinators"
|
||||
requires = "bytes"
|
||||
archive(byte) = "sequence.cma"
|
||||
|
|
@ -9,7 +9,7 @@ archive(native) = "sequence.cmxa"
|
|||
archive(native, plugin) = "sequence.cmxs"
|
||||
exists_if = "sequence.cma"
|
||||
package "invert" (
|
||||
version = "0.5.4"
|
||||
version = "0.5.5"
|
||||
description = "Simple sequence (iterator) datatype and combinators"
|
||||
requires = "sequence delimcc"
|
||||
archive(byte) = "invert.cma"
|
||||
|
|
@ -20,7 +20,7 @@ package "invert" (
|
|||
)
|
||||
|
||||
package "bigarray" (
|
||||
version = "0.5.4"
|
||||
version = "0.5.5"
|
||||
description = "Simple sequence (iterator) datatype and combinators"
|
||||
requires = "sequence bigarray"
|
||||
archive(byte) = "bigarray.cma"
|
||||
|
|
|
|||
12
Makefile
12
Makefile
|
|
@ -66,4 +66,16 @@ update_next_tag:
|
|||
sed -i "s/NEXT_VERSION/$(VERSION)/g" $(SOURCE)
|
||||
sed -i "s/NEXT_RELEASE/$(VERSION)/g" $(SOURCE)
|
||||
|
||||
NAME_VERSION := sequence.$(VERSION)
|
||||
URL := https://github.com/c-cube/sequence/archive/$(VERSION).tar.gz
|
||||
|
||||
release:
|
||||
git tag -a $(VERSION) -m "Version $(VERSION)."
|
||||
git push origin $(VERSION)
|
||||
opam publish prepare $(NAME_VERSION) $(URL)
|
||||
cp descr $(NAME_VERSION)
|
||||
echo "submit?"
|
||||
@read
|
||||
opam publish submit $(NAME_VERSION)
|
||||
|
||||
.PHONY: benchs tests examples update_next_tag push_doc push_stable
|
||||
|
|
|
|||
4
_oasis
4
_oasis
|
|
@ -1,6 +1,6 @@
|
|||
OASISFormat: 0.4
|
||||
Name: sequence
|
||||
Version: 0.5.4
|
||||
Version: 0.5.5
|
||||
Homepage: https://github.com/c-cube/sequence
|
||||
Authors: Simon Cruanes
|
||||
License: BSD-2-clause
|
||||
|
|
@ -29,7 +29,7 @@ Flag bigarray
|
|||
|
||||
Library "sequence"
|
||||
Path: .
|
||||
Modules: Sequence
|
||||
Modules: Sequence, SequenceLabels
|
||||
BuildDepends: bytes
|
||||
|
||||
Library "invert"
|
||||
|
|
|
|||
3
_tags
3
_tags
|
|
@ -51,3 +51,6 @@ true: annot, bin_annot
|
|||
<bench/*.ml{,i,y}>: use_sequence
|
||||
# OASIS_STOP
|
||||
true: bin_annot
|
||||
<**/*.ml>: warn_A, warn(-4)
|
||||
true: mark_tag_used
|
||||
<sequenceLabels.cm*>: nolabels
|
||||
|
|
|
|||
6
descr
Normal file
6
descr
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
Simple and lightweight sequence abstract data type.
|
||||
|
||||
Simple sequence abstract data type, intended to transfer a finite number of
|
||||
elements from one data structure to another. Some transformations on sequences,
|
||||
like `filter`, `map`, `take`, `drop` and `append` can be performed before the
|
||||
sequence is iterated/folded on.
|
||||
21
opam
Normal file
21
opam
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
opam-version: "1.2"
|
||||
author: "Simon Cruanes"
|
||||
maintainer: "simon.cruanes@inria.fr"
|
||||
build: [
|
||||
["./configure" "--disable-docs"
|
||||
"--%{delimcc:enable}%-invert"
|
||||
"--%{base-bigarray:enable}%-bigarray"
|
||||
]
|
||||
[make "build"]
|
||||
]
|
||||
install: [make "install"]
|
||||
remove: [
|
||||
["ocamlfind" "remove" "sequence"]
|
||||
]
|
||||
depends: ["ocamlfind" "base-bytes"]
|
||||
tags: [ "sequence" "iterator" "iter" "fold" ]
|
||||
homepage: "https://github.com/c-cube/sequence/"
|
||||
depopts: ["delimcc" "base-bigarray"]
|
||||
doc: "http://cedeela.fr/~simon/software/sequence/Sequence.html"
|
||||
bug-reports: "https://github.com/c-cube/sequence/issues"
|
||||
dev-repo: "https://github.com/c-cube/sequence.git"
|
||||
37
sequence.ml
37
sequence.ml
|
|
@ -40,7 +40,7 @@ let rec from_fun f k = match f () with
|
|||
| None -> ()
|
||||
| Some x -> k x; from_fun f k
|
||||
|
||||
let empty k = ()
|
||||
let empty _ = ()
|
||||
|
||||
let singleton x k = k x
|
||||
let return x k = k x
|
||||
|
|
@ -152,10 +152,6 @@ module MList = struct
|
|||
let of_seq seq =
|
||||
of_seq_with seq (fun _ -> ())
|
||||
|
||||
let is_empty = function
|
||||
| Nil -> true
|
||||
| Cons _ -> false
|
||||
|
||||
let rec iter f l = match l with
|
||||
| Nil -> ()
|
||||
| Cons (a, n, tl) ->
|
||||
|
|
@ -199,7 +195,7 @@ module MList = struct
|
|||
cur := !tl;
|
||||
i := 0;
|
||||
get_next arg
|
||||
| Cons (a, n, _) ->
|
||||
| Cons (a, _, _) ->
|
||||
let x = a.(!i) in
|
||||
incr i;
|
||||
Some x
|
||||
|
|
@ -214,7 +210,7 @@ module MList = struct
|
|||
let rec make (l,i) () = match l with
|
||||
| Nil -> `Nil
|
||||
| Cons (_, n, tl) when i = !n -> make (!tl,0) ()
|
||||
| Cons (a, n, _) -> `Cons (a.(i), make (l,i+1))
|
||||
| Cons (a, _, _) -> `Cons (a.(i), make (l,i+1))
|
||||
in make (l,0)
|
||||
end
|
||||
|
||||
|
|
@ -351,6 +347,21 @@ let take_while p seq k =
|
|||
seq (fun x -> if p x then k x else raise ExitTakeWhile)
|
||||
with ExitTakeWhile -> ()
|
||||
|
||||
exception ExitFoldWhile
|
||||
|
||||
let fold_while f s seq =
|
||||
let state = ref s in
|
||||
let consume x =
|
||||
let acc, cont = f (!state) x in
|
||||
state := acc;
|
||||
match cont with
|
||||
| `Stop -> raise ExitFoldWhile
|
||||
| `Continue -> ()
|
||||
in
|
||||
try
|
||||
seq consume; !state
|
||||
with ExitFoldWhile -> !state
|
||||
|
||||
let drop n seq k =
|
||||
let count = ref 0 in
|
||||
seq (fun x -> if !count >= n then k x else incr count)
|
||||
|
|
@ -411,7 +422,7 @@ let is_empty seq =
|
|||
|
||||
(** {2 Transform a sequence} *)
|
||||
|
||||
let empty2 k = ()
|
||||
let empty2 _ = ()
|
||||
|
||||
let is_empty2 seq2 =
|
||||
try ignore (seq2 (fun _ _ -> raise ExitIsEmpty)); true
|
||||
|
|
@ -525,9 +536,9 @@ let of_hashtbl h k = Hashtbl.iter (fun a b -> k (a, b)) h
|
|||
|
||||
let of_hashtbl2 h k = Hashtbl.iter k h
|
||||
|
||||
let hashtbl_keys h k = Hashtbl.iter (fun a b -> k a) h
|
||||
let hashtbl_keys h k = Hashtbl.iter (fun a _ -> k a) h
|
||||
|
||||
let hashtbl_values h k = Hashtbl.iter (fun a b -> k b) h
|
||||
let hashtbl_values h k = Hashtbl.iter (fun _ b -> k b) h
|
||||
|
||||
let of_str s k = String.iter k s
|
||||
|
||||
|
|
@ -613,16 +624,16 @@ module Set = struct
|
|||
end
|
||||
|
||||
(** Create an enriched Set module from the given one *)
|
||||
module Adapt(X : Set.S) = struct
|
||||
module Adapt(X : Set.S) : S with type elt = X.elt and type t = X.t = struct
|
||||
let to_seq set k = X.iter k set
|
||||
|
||||
let of_seq seq = fold (fun set x -> X.add x set) X.empty seq
|
||||
|
||||
let of_list l = of_seq (of_list l)
|
||||
|
||||
let to_list set = to_list (to_seq set)
|
||||
|
||||
include X
|
||||
|
||||
let of_list l = List.fold_left (fun set x -> add x set) empty l
|
||||
end
|
||||
|
||||
(** Functor to build an extended Set module from an ordered type *)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
# OASIS_START
|
||||
# DO NOT EDIT (digest: 3ff39d3acb327553070a64ef0cb321d5)
|
||||
# DO NOT EDIT (digest: 8c0ffebbdb3e063d4b3e5cc00517b199)
|
||||
Sequence
|
||||
SequenceLabels
|
||||
# OASIS_STOP
|
||||
|
|
|
|||
|
|
@ -119,10 +119,10 @@ val iter : ('a -> unit) -> 'a t -> unit
|
|||
val iteri : (int -> 'a -> unit) -> 'a t -> unit
|
||||
(** Iterate on elements and their index in the sequence *)
|
||||
|
||||
val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b
|
||||
val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
|
||||
(** Fold over elements of the sequence, consuming it *)
|
||||
|
||||
val foldi : ('b -> int -> 'a -> 'b) -> 'b -> 'a t -> 'b
|
||||
val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a
|
||||
(** Fold over elements of the sequence and their index, consuming it *)
|
||||
|
||||
val map : ('a -> 'b) -> 'a t -> 'b t
|
||||
|
|
@ -272,6 +272,11 @@ val take_while : ('a -> bool) -> 'a t -> 'a t
|
|||
Will work on an infinite sequence [s] if the predicate is false for at
|
||||
least one element of [s]. *)
|
||||
|
||||
val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a
|
||||
(** Folds over elements of the sequence, stopping early if the accumulator
|
||||
returns [('a, `Stop)]
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val drop : int -> 'a t -> 'a t
|
||||
(** Drop the [n] first elements of the sequence. Lazy. *)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
# OASIS_START
|
||||
# DO NOT EDIT (digest: 3ff39d3acb327553070a64ef0cb321d5)
|
||||
# DO NOT EDIT (digest: 8c0ffebbdb3e063d4b3e5cc00517b199)
|
||||
Sequence
|
||||
SequenceLabels
|
||||
# OASIS_STOP
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
# OASIS_START
|
||||
# DO NOT EDIT (digest: 3ff39d3acb327553070a64ef0cb321d5)
|
||||
# DO NOT EDIT (digest: 8c0ffebbdb3e063d4b3e5cc00517b199)
|
||||
Sequence
|
||||
SequenceLabels
|
||||
# OASIS_STOP
|
||||
|
|
|
|||
1
sequenceLabels.ml
Normal file
1
sequenceLabels.ml
Normal file
|
|
@ -0,0 +1 @@
|
|||
include Sequence
|
||||
572
sequenceLabels.mli
Normal file
572
sequenceLabels.mli
Normal file
|
|
@ -0,0 +1,572 @@
|
|||
(*
|
||||
copyright (c) 2013, simon cruanes
|
||||
all rights reserved.
|
||||
|
||||
redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer. redistributions in binary
|
||||
form must reproduce the above copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other materials provided with
|
||||
the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*)
|
||||
|
||||
(** {1 Simple and Efficient Iterators}
|
||||
|
||||
Version of {!Sequence} with labels
|
||||
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
type +'a t = ('a -> unit) -> unit
|
||||
(** A sequence of values of type ['a]. If you give it a function ['a -> unit]
|
||||
it will be applied to every element of the sequence successively. *)
|
||||
|
||||
type +'a sequence = 'a t
|
||||
|
||||
type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit
|
||||
(** Sequence of pairs of values of type ['a] and ['b]. *)
|
||||
|
||||
(** {2 Build a sequence} *)
|
||||
|
||||
val from_iter : (('a -> unit) -> unit) -> 'a t
|
||||
(** Build a sequence from a iter function *)
|
||||
|
||||
val from_fun : (unit -> 'a option) -> 'a t
|
||||
(** Call the function repeatedly until it returns None. This
|
||||
sequence is transient, use {!persistent} if needed! *)
|
||||
|
||||
val empty : 'a t
|
||||
(** Empty sequence. It contains no element. *)
|
||||
|
||||
val singleton : 'a -> 'a t
|
||||
(** Singleton sequence, with exactly one element. *)
|
||||
|
||||
val doubleton : 'a -> 'a -> 'a t
|
||||
(** Sequence with exactly two elements *)
|
||||
|
||||
val cons : 'a -> 'a t -> 'a t
|
||||
(** [cons x l] yields [x], then yields from [l].
|
||||
Same as [append (singleton x) l] *)
|
||||
|
||||
val snoc : 'a t -> 'a -> 'a t
|
||||
(** Same as {!cons} but yields the element after iterating on [l] *)
|
||||
|
||||
val return : 'a -> 'a t
|
||||
(** Synonym to {!singleton} *)
|
||||
|
||||
val pure : 'a -> 'a t
|
||||
(** Synonym to {!singleton} *)
|
||||
|
||||
val repeat : 'a -> 'a t
|
||||
(** Infinite sequence of the same element. You may want to look
|
||||
at {!take} and the likes if you iterate on it. *)
|
||||
|
||||
val iterate : ('a -> 'a) -> 'a -> 'a t
|
||||
(** [iterate f x] is the infinite sequence [x, f(x), f(f(x)), ...] *)
|
||||
|
||||
val forever : (unit -> 'b) -> 'b t
|
||||
(** Sequence that calls the given function to produce elements.
|
||||
The sequence may be transient (depending on the function), and definitely
|
||||
is infinite. You may want to use {!take} and {!persistent}. *)
|
||||
|
||||
val cycle : 'a t -> 'a t
|
||||
(** Cycle forever through the given sequence. Assume the given sequence can
|
||||
be traversed any amount of times (not transient). This yields an
|
||||
infinite sequence, you should use something like {!take} not to loop
|
||||
forever. *)
|
||||
|
||||
(** {2 Consume a sequence} *)
|
||||
|
||||
val iter : f:('a -> unit) -> 'a t -> unit
|
||||
(** Consume the sequence, passing all its arguments to the function.
|
||||
Basically [iter f seq] is just [seq f]. *)
|
||||
|
||||
val iteri : f:(int -> 'a -> unit) -> 'a t -> unit
|
||||
(** Iterate on elements and their index in the sequence *)
|
||||
|
||||
val fold : f:('a -> 'b -> 'a) -> init:'a -> 'b t -> 'a
|
||||
(** Fold over elements of the sequence, consuming it *)
|
||||
|
||||
val foldi : f:('a -> int -> 'b -> 'a) -> init:'a -> 'b t -> 'a
|
||||
(** Fold over elements of the sequence and their index, consuming it *)
|
||||
|
||||
val map : f:('a -> 'b) -> 'a t -> 'b t
|
||||
(** Map objects of the sequence into other elements, lazily *)
|
||||
|
||||
val mapi : f:(int -> 'a -> 'b) -> 'a t -> 'b t
|
||||
(** Map objects, along with their index in the sequence *)
|
||||
|
||||
val for_all : f:('a -> bool) -> 'a t -> bool
|
||||
(** Do all elements satisfy the predicate? *)
|
||||
|
||||
val exists : f:('a -> bool) -> 'a t -> bool
|
||||
(** Exists there some element satisfying the predicate? *)
|
||||
|
||||
val mem : ?eq:('a -> 'a -> bool) -> x:'a -> 'a t -> bool
|
||||
(** Is the value a member of the sequence?
|
||||
@param eq the equality predicate to use (default [(=)]) *)
|
||||
|
||||
val find : f:('a -> 'b option) -> 'a t -> 'b option
|
||||
(** Find the first element on which the function doesn't return [None] *)
|
||||
|
||||
val length : 'a t -> int
|
||||
(** How long is the sequence? Forces the sequence. *)
|
||||
|
||||
val is_empty : 'a t -> bool
|
||||
(** Is the sequence empty? Forces the sequence. *)
|
||||
|
||||
(** {2 Transform a sequence} *)
|
||||
|
||||
val filter : f:('a -> bool) -> 'a t -> 'a t
|
||||
(** Filter on elements of the sequence *)
|
||||
|
||||
val append : 'a t -> 'a t -> 'a t
|
||||
(** Append two sequences. Iterating on the result is like iterating
|
||||
on the first, then on the second. *)
|
||||
|
||||
val concat : 'a t t -> 'a t
|
||||
(** Concatenate a sequence of sequences into one sequence. *)
|
||||
|
||||
val flatten : 'a t t -> 'a t
|
||||
(** Alias for {!concat} *)
|
||||
|
||||
val flatMap : f:('a -> 'b t) -> 'a t -> 'b t
|
||||
(** Monadic bind. Intuitively, it applies the function to every element of the
|
||||
initial sequence, and calls {!concat}.
|
||||
@deprecated use {!flat_map} *)
|
||||
|
||||
val flat_map : f:('a -> 'b t) -> 'a t -> 'b t
|
||||
(** Alias to {!flatMap} with a more explicit name *)
|
||||
|
||||
val fmap : f:('a -> 'b option) -> 'a t -> 'b t
|
||||
(** Specialized version of {!flatMap} for options.
|
||||
@deprecated use {!filter_map} *)
|
||||
|
||||
val filter_map : f:('a -> 'b option) -> 'a t -> 'b t
|
||||
(** Alias to {!fmap} with a more explicit name *)
|
||||
|
||||
val intersperse : x:'a -> 'a t -> 'a t
|
||||
(** Insert the single element between every element of the sequence *)
|
||||
|
||||
(** {2 Caching} *)
|
||||
|
||||
val persistent : 'a t -> 'a t
|
||||
(** Iterate on the sequence, storing elements in an efficient internal structure..
|
||||
The resulting sequence can be iterated on as many times as needed.
|
||||
{b Note}: calling persistent on an already persistent 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. *)
|
||||
|
||||
(** {2 Misc} *)
|
||||
|
||||
val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
|
||||
(** Sort the sequence. Eager, O(n) ram and O(n ln(n)) time.
|
||||
It iterates on elements of the argument sequence immediately,
|
||||
before it sorts them. *)
|
||||
|
||||
val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
|
||||
(** Sort the sequence and remove duplicates. Eager, same as [sort] *)
|
||||
|
||||
val group : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t
|
||||
(** Group equal consecutive elements. *)
|
||||
|
||||
val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t
|
||||
(** Remove consecutive duplicate elements. Basically this is
|
||||
like [fun seq -> map List.hd (group seq)]. *)
|
||||
|
||||
val product : 'a t -> 'b t -> ('a * 'b) t
|
||||
(** Cartesian product of the sequences. When calling [product a b],
|
||||
the caller {b MUST} ensure that [b] can be traversed as many times
|
||||
as required (several times), possibly by calling {!persistent} on it
|
||||
beforehand. *)
|
||||
|
||||
val product2 : 'a t -> 'b t -> ('a, 'b) t2
|
||||
(** Binary version of {!product}. Same requirements. *)
|
||||
|
||||
val join : join_row:('a -> 'b -> 'c option) -> 'a t -> 'b t -> 'c t
|
||||
(** [join ~join_row a b] combines every element of [a] with every
|
||||
element of [b] using [join_row]. If [join_row] returns None, then
|
||||
the two elements do not combine. Assume that [b] allows for multiple
|
||||
iterations. *)
|
||||
|
||||
val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t
|
||||
(** [unfoldr f b] will apply [f] to [b]. If it
|
||||
yields [Some (x,b')] then [x] is returned
|
||||
and unfoldr recurses with [b']. *)
|
||||
|
||||
val scan : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b t
|
||||
(** Sequence of intermediate results *)
|
||||
|
||||
val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
|
||||
(** Max element of the sequence, using the given comparison function.
|
||||
@return None if the sequence is empty, Some [m] where [m] is the maximal
|
||||
element otherwise *)
|
||||
|
||||
val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
|
||||
(** Min element of the sequence, using the given comparison function.
|
||||
see {!max} for more details. *)
|
||||
|
||||
val head : 'a t -> 'a option
|
||||
(** First element, if any, otherwise [None] *)
|
||||
|
||||
val head_exn : 'a t -> 'a
|
||||
(** First element, if any, fails
|
||||
@raise Invalid_argument if the sequence is empty *)
|
||||
|
||||
val take : int -> 'a t -> 'a t
|
||||
(** Take at most [n] elements from the sequence. Works on infinite
|
||||
sequences. *)
|
||||
|
||||
val take_while : f:('a -> bool) -> 'a t -> 'a t
|
||||
(** Take elements while they satisfy the predicate, then stops iterating.
|
||||
Will work on an infinite sequence [s] if the predicate is false for at
|
||||
least one element of [s]. *)
|
||||
|
||||
val fold_while : f:('a -> 'b -> 'a * [`Stop | `Continue]) -> init:'a -> 'b t -> 'a
|
||||
(** Folds over elements of the sequence, stopping early if the accumulator
|
||||
returns [('a, `Stop)] *)
|
||||
|
||||
val drop : int -> 'a t -> 'a t
|
||||
(** Drop the [n] first elements of the sequence. Lazy. *)
|
||||
|
||||
val drop_while : f:('a -> bool) -> 'a t -> 'a t
|
||||
(** Predicate version of {!drop} *)
|
||||
|
||||
val rev : 'a t -> 'a t
|
||||
(** Reverse the sequence. O(n) memory and time, needs the
|
||||
sequence to be finite. The result is persistent and does
|
||||
not depend on the input being repeatable. *)
|
||||
|
||||
(** {2 Binary sequences} *)
|
||||
|
||||
val empty2 : ('a, 'b) t2
|
||||
|
||||
val is_empty2 : (_, _) t2 -> bool
|
||||
|
||||
val length2 : (_, _) t2 -> int
|
||||
|
||||
val zip : ('a, 'b) t2 -> ('a * 'b) t
|
||||
|
||||
val unzip : ('a * 'b) t -> ('a, 'b) t2
|
||||
|
||||
val zip_i : 'a t -> (int, 'a) t2
|
||||
(** Zip elements of the sequence with their index in the sequence *)
|
||||
|
||||
val fold2 : f:('c -> 'a -> 'b -> 'c) -> init:'c -> ('a, 'b) t2 -> 'c
|
||||
|
||||
val iter2 : f:('a -> 'b -> unit) -> ('a, 'b) t2 -> unit
|
||||
|
||||
val map2 : f:('a -> 'b -> 'c) -> ('a, 'b) t2 -> 'c t
|
||||
|
||||
val map2_2 : ('a -> 'b -> 'c) -> ('a -> 'b -> 'd) -> ('a, 'b) t2 -> ('c, 'd) t2
|
||||
(** [map2_2 f g seq2] maps each [x, y] of seq2 into [f x y, g x y] *)
|
||||
|
||||
(** {2 Basic data structures converters} *)
|
||||
|
||||
val to_list : 'a t -> 'a list
|
||||
(** Convert the sequence into a list. Preserves order of elements.
|
||||
This function is tail-recursive, but consumes 2*n memory.
|
||||
If order doesn't matter to you, consider {!to_rev_list}. *)
|
||||
|
||||
val to_rev_list : 'a t -> 'a list
|
||||
(** Get the list of the reversed sequence (more efficient than {!to_list}) *)
|
||||
|
||||
val of_list : 'a list -> 'a t
|
||||
|
||||
val on_list : ('a t -> 'b t) -> 'a list -> 'b list
|
||||
(** [on_list f l] is equivalent to [to_list @@ f @@ of_list l]. *)
|
||||
|
||||
val to_opt : 'a t -> 'a option
|
||||
(** Alias to {!head} *)
|
||||
|
||||
val to_array : 'a t -> 'a array
|
||||
(** Convert to an array. Currently not very efficient because
|
||||
an 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 of_array2 : 'a array -> (int, 'a) t2
|
||||
|
||||
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_opt : 'a option -> 'a t
|
||||
(** Iterate on 0 or 1 values. *)
|
||||
|
||||
val of_stream : 'a Stream.t -> 'a t
|
||||
(** Sequence of elements of a stream (usable only once) *)
|
||||
|
||||
val to_stream : 'a t -> 'a Stream.t
|
||||
(** Convert to a stream. linear in memory and time (a copy is made in memory) *)
|
||||
|
||||
val to_stack : 'a Stack.t -> 'a t -> unit
|
||||
(** Push elements of the sequence on the stack *)
|
||||
|
||||
val of_stack : 'a Stack.t -> 'a t
|
||||
(** Sequence of elements of the stack (same order as [Stack.iter]) *)
|
||||
|
||||
val to_queue : 'a Queue.t -> 'a t -> unit
|
||||
(** Push elements of the sequence into the queue *)
|
||||
|
||||
val of_queue : 'a Queue.t -> 'a t
|
||||
(** Sequence of elements contained in the queue, FIFO order *)
|
||||
|
||||
val hashtbl_add : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
|
||||
(** Add elements of the sequence to the hashtable, with
|
||||
Hashtbl.add *)
|
||||
|
||||
val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
|
||||
(** Add elements of the sequence to the hashtable, with
|
||||
Hashtbl.replace (erases conflicting bindings) *)
|
||||
|
||||
val to_hashtbl : ('a * 'b) t -> ('a, 'b) Hashtbl.t
|
||||
(** Build a hashtable from a sequence of key/value pairs *)
|
||||
|
||||
val to_hashtbl2 : ('a, 'b) t2 -> ('a, 'b) Hashtbl.t
|
||||
(** Build a hashtable from a sequence of key/value pairs *)
|
||||
|
||||
val of_hashtbl : ('a, 'b) Hashtbl.t -> ('a * 'b) t
|
||||
(** Sequence of key/value pairs from the hashtable *)
|
||||
|
||||
val of_hashtbl2 : ('a, 'b) Hashtbl.t -> ('a, 'b) t2
|
||||
(** Sequence of key/value pairs from the hashtable *)
|
||||
|
||||
val hashtbl_keys : ('a, 'b) Hashtbl.t -> 'a t
|
||||
val hashtbl_values : ('a, 'b) Hashtbl.t -> 'b t
|
||||
|
||||
val of_str : string -> char t
|
||||
val to_str : char t -> string
|
||||
|
||||
val concat_str : string t -> string
|
||||
(** Concatenate strings together, eagerly.
|
||||
Also see {!intersperse} to add a separator. *)
|
||||
|
||||
exception OneShotSequence
|
||||
(** Raised when the user tries to iterate several times on
|
||||
a transient iterator *)
|
||||
|
||||
val of_in_channel : in_channel -> char t
|
||||
(** Iterates on characters of the input (can block when one
|
||||
iterates over the sequence). If you need to iterate
|
||||
several times on this sequence, use {!persistent}.
|
||||
@raise OneShotSequence when used more than once. *)
|
||||
|
||||
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. Also see
|
||||
{!(--)} for an infix version. *)
|
||||
|
||||
val int_range_dec : start:int -> stop:int -> int t
|
||||
(** Iterator on decreasing integers in [stop...start] by steps -1.
|
||||
See {!(--^)} for an infix version *)
|
||||
|
||||
val of_set : (module Set.S with type elt = 'a and type t = 'b) -> 'b -> 'a t
|
||||
(** Convert the given set to a sequence. The set module must be provided. *)
|
||||
|
||||
val to_set : (module Set.S with type elt = 'a and type t = 'b) -> 'a t -> 'b
|
||||
(** Convert the sequence to a set, given the proper set module *)
|
||||
|
||||
type 'a gen = unit -> 'a option
|
||||
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
|
||||
|
||||
val of_gen : 'a gen -> 'a t
|
||||
(** Traverse eagerly the generator and build a sequence from it *)
|
||||
|
||||
val to_gen : 'a t -> 'a gen
|
||||
(** Make the sequence persistent (O(n)) and then iterate on it. Eager. *)
|
||||
|
||||
val of_klist : 'a klist -> 'a t
|
||||
(** Iterate on the lazy list *)
|
||||
|
||||
val to_klist : 'a t -> 'a klist
|
||||
(** Make the sequence persistent and then iterate on it. Eager. *)
|
||||
|
||||
(** {2 Functorial conversions between sets and sequences} *)
|
||||
|
||||
module Set : sig
|
||||
module type S = sig
|
||||
include Set.S
|
||||
val of_seq : elt sequence -> t
|
||||
val to_seq : t -> elt sequence
|
||||
val to_list : t -> elt list
|
||||
val of_list : elt list -> t
|
||||
end
|
||||
|
||||
(** Create an enriched Set module from the given one *)
|
||||
module Adapt(X : Set.S) : S with type elt = X.elt and type t = X.t
|
||||
|
||||
(** Functor to build an extended Set module from an ordered type *)
|
||||
module Make(X : Set.OrderedType) : S with type elt = X.t
|
||||
end
|
||||
|
||||
(** {2 Conversion between maps and sequences.} *)
|
||||
|
||||
module Map : sig
|
||||
module type S = sig
|
||||
include Map.S
|
||||
val to_seq : 'a t -> (key * 'a) sequence
|
||||
val of_seq : (key * 'a) sequence -> 'a t
|
||||
val keys : 'a t -> key sequence
|
||||
val values : 'a t -> 'a sequence
|
||||
val to_list : 'a t -> (key * 'a) list
|
||||
val of_list : (key * 'a) list -> 'a t
|
||||
end
|
||||
|
||||
(** Adapt a pre-existing Map module to make it sequence-aware *)
|
||||
module Adapt(M : Map.S) : S with type key = M.key and type 'a t = 'a M.t
|
||||
|
||||
(** Create an enriched Map module, with sequence-aware functions *)
|
||||
module Make(V : Map.OrderedType) : S with type key = V.t
|
||||
end
|
||||
|
||||
(** {2 Infinite sequences of random values} *)
|
||||
|
||||
val random_int : int -> int t
|
||||
(** Infinite sequence of random integers between 0 and
|
||||
the given higher bound (see Random.int) *)
|
||||
|
||||
val random_bool : bool t
|
||||
(** Infinite sequence of random bool values *)
|
||||
|
||||
val random_float : float -> float t
|
||||
|
||||
val random_array : 'a array -> 'a t
|
||||
(** Sequence of choices of an element in the array *)
|
||||
|
||||
val random_list : 'a list -> 'a t
|
||||
(** Infinite sequence of random elements of the list. Basically the
|
||||
same as {!random_array}. *)
|
||||
|
||||
(** {2 Infix functions} *)
|
||||
|
||||
module Infix : sig
|
||||
val (--) : int -> int -> int t
|
||||
(** [a -- b] is the range of integers from [a] to [b], both included,
|
||||
in increasing order. It will therefore be empty if [a > b]. *)
|
||||
|
||||
val (--^) : int -> int -> int t
|
||||
(** [a --^ b] is the range of integers from [b] to [a], both included,
|
||||
in decreasing order (starts from [a]).
|
||||
It will therefore be empty if [a < b]. *)
|
||||
|
||||
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
||||
(** Monadic bind (infix version of {!flat_map} *)
|
||||
|
||||
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
|
||||
(** Infix version of {!map} *)
|
||||
|
||||
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
|
||||
(** Applicative operator (product+application) *)
|
||||
|
||||
val (<+>) : 'a t -> 'a t -> 'a t
|
||||
(** Concatenation of sequences *)
|
||||
end
|
||||
|
||||
include module type of Infix
|
||||
|
||||
|
||||
(** {2 Pretty printing of sequences} *)
|
||||
|
||||
val pp_seq : ?sep:string -> (Format.formatter -> 'a -> unit) ->
|
||||
Format.formatter -> 'a t -> unit
|
||||
(** Pretty print a sequence of ['a], using the given pretty printer
|
||||
to print each elements. An optional separator string can be provided. *)
|
||||
|
||||
val pp_buf : ?sep:string -> (Buffer.t -> 'a -> unit) ->
|
||||
Buffer.t -> 'a t -> unit
|
||||
(** Print into a buffer *)
|
||||
|
||||
val to_string : ?sep:string -> ('a -> string) -> 'a t -> string
|
||||
(** Print into a string *)
|
||||
|
||||
(** {2 Basic IO}
|
||||
|
||||
Very basic interface to manipulate files as sequence of chunks/lines. The
|
||||
sequences take care of opening and closing files properly; every time
|
||||
one iterates over a sequence, the file is opened/closed again.
|
||||
|
||||
Example: copy a file ["a"] into file ["b"], removing blank lines:
|
||||
|
||||
{[
|
||||
Sequence.(IO.lines_of "a" |> filter (fun l-> l<> "") |> IO.write_lines "b");;
|
||||
]}
|
||||
|
||||
By chunks of [4096] bytes:
|
||||
|
||||
{[
|
||||
Sequence.IO.(chunks_of ~size:4096 "a" |> write_to "b");;
|
||||
]}
|
||||
|
||||
Read the lines of a file into a list:
|
||||
|
||||
{[
|
||||
Sequence.IO.lines "a" |> Sequence.to_list
|
||||
]}
|
||||
|
||||
*)
|
||||
|
||||
module IO : sig
|
||||
val lines_of : ?mode:int -> ?flags:open_flag list ->
|
||||
string -> string t
|
||||
(** [lines_of filename] reads all lines of the given file. It raises the
|
||||
same exception as would opening the file and read from it, except
|
||||
from [End_of_file] (which is caught). The file is {b always} properly
|
||||
closed.
|
||||
Every time the sequence is iterated on, the file is opened again, so
|
||||
different iterations might return different results
|
||||
@param mode default [0o644]
|
||||
@param flags default: [[Open_rdonly]] *)
|
||||
|
||||
val chunks_of : ?mode:int -> ?flags:open_flag list -> ?size:int ->
|
||||
string -> string t
|
||||
(** Read chunks of the given [size] from the file. The last chunk might be
|
||||
smaller. Behaves like {!lines_of} regarding errors and options.
|
||||
Every time the sequence is iterated on, the file is opened again, so
|
||||
different iterations might return different results *)
|
||||
|
||||
val write_to : ?mode:int -> ?flags:open_flag list ->
|
||||
string -> string t -> unit
|
||||
(** [write_to filename seq] writes all strings from [seq] into the given
|
||||
file. It takes care of opening and closing the file.
|
||||
@param mode default [0o644]
|
||||
@param flags used by [open_out_gen]. Default: [[Open_creat;Open_wronly]]. *)
|
||||
|
||||
val write_bytes_to : ?mode:int -> ?flags:open_flag list ->
|
||||
string -> Bytes.t t -> unit
|
||||
(** *)
|
||||
|
||||
val write_lines : ?mode:int -> ?flags:open_flag list ->
|
||||
string -> string t -> unit
|
||||
(** Same as {!write_to}, but intercales ['\n'] between each string *)
|
||||
|
||||
val write_bytes_lines : ?mode:int -> ?flags:open_flag list ->
|
||||
string -> Bytes.t t -> unit
|
||||
end
|
||||
8
setup.ml
8
setup.ml
|
|
@ -1,7 +1,7 @@
|
|||
(* setup.ml generated for the first time by OASIS v0.4.4 *)
|
||||
|
||||
(* OASIS_START *)
|
||||
(* DO NOT EDIT (digest: 99b277a969b94ce64e720af9e5ba6929) *)
|
||||
(* DO NOT EDIT (digest: 333f749d9a0c9bcd48d939db40a13c4b) *)
|
||||
(*
|
||||
Regenerated by OASIS v0.4.5
|
||||
Visit http://oasis.forge.ocamlcore.org for more information and
|
||||
|
|
@ -6861,7 +6861,7 @@ let setup_t =
|
|||
alpha_features = [];
|
||||
beta_features = [];
|
||||
name = "sequence";
|
||||
version = "0.5.4";
|
||||
version = "0.5.5";
|
||||
license =
|
||||
OASISLicense.DEP5License
|
||||
(OASISLicense.DEP5Unit
|
||||
|
|
@ -6975,7 +6975,7 @@ let setup_t =
|
|||
bs_nativeopt = [(OASISExpr.EBool true, [])]
|
||||
},
|
||||
{
|
||||
lib_modules = ["Sequence"];
|
||||
lib_modules = ["Sequence"; "SequenceLabels"];
|
||||
lib_pack = false;
|
||||
lib_internal_modules = [];
|
||||
lib_findlib_parent = None;
|
||||
|
|
@ -7280,7 +7280,7 @@ let setup_t =
|
|||
};
|
||||
oasis_fn = Some "_oasis";
|
||||
oasis_version = "0.4.5";
|
||||
oasis_digest = Some "\143pX\233\t\217\232\\d\023B\027\020*\019W";
|
||||
oasis_digest = Some "\179Sa\175xP\026d\164\216\201\198\001\028\141O";
|
||||
oasis_exec = None;
|
||||
oasis_setup_args = [];
|
||||
setup_update = false
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
open OUnit
|
||||
|
||||
module S = Sequence
|
||||
open Sequence.Infix
|
||||
|
||||
let pp_ilist l =
|
||||
let b = Buffer.create 15 in
|
||||
|
|
@ -24,14 +23,14 @@ let test_repeat () =
|
|||
()
|
||||
|
||||
let test_concat () =
|
||||
let s1 = (1 -- 5) in
|
||||
let s2 = (6 -- 10) in
|
||||
let s1 = S.(1 -- 5) in
|
||||
let s2 = S.(6 -- 10) in
|
||||
let l = [1;2;3;4;5;6;7;8;9;10] in
|
||||
OUnit.assert_equal l (S.to_list (S.append s1 s2));
|
||||
()
|
||||
|
||||
let test_fold () =
|
||||
let n = (1 -- 10)
|
||||
let n = S.(1 -- 10)
|
||||
|> S.fold (+) 0 in
|
||||
OUnit.assert_equal 55 n;
|
||||
()
|
||||
|
|
@ -43,34 +42,40 @@ let test_foldi () =
|
|||
OUnit.assert_equal [1, "world"; 0, "hello"] l;
|
||||
()
|
||||
|
||||
let test_fold_while () =
|
||||
let n = S.of_list [true;true;false;true]
|
||||
|> S.fold_while (fun acc b -> if b then acc+1, `Continue else acc, `Stop) 0 in
|
||||
OUnit.assert_equal 2 n;
|
||||
()
|
||||
|
||||
let test_exists () =
|
||||
(1 -- 100)
|
||||
S.(1 -- 100)
|
||||
|> S.exists (fun x -> x = 59)
|
||||
|> OUnit.assert_bool "exists";
|
||||
(1 -- 100)
|
||||
S.(1 -- 100)
|
||||
|> S.exists (fun x -> x < 0)
|
||||
|> (fun x -> not x)
|
||||
|> OUnit.assert_bool "not exists";
|
||||
()
|
||||
|
||||
let test_length () =
|
||||
(1 -- 1000) |> S.length |> OUnit.assert_equal 1000
|
||||
S.(1 -- 1000) |> S.length |> OUnit.assert_equal 1000
|
||||
|
||||
let test_concat () =
|
||||
1 -- 1000
|
||||
|> S.map (fun i -> (i -- (i+1)))
|
||||
let test_concat2 () =
|
||||
S.(1 -- 1000)
|
||||
|> S.map (fun i -> S.(i -- (i+1)))
|
||||
|> S.concat
|
||||
|> S.length
|
||||
|> OUnit.assert_equal 2000
|
||||
|
||||
let test_flatMap () =
|
||||
1 -- 1000
|
||||
|> S.flatMap (fun i -> (i -- (i+1)))
|
||||
S.(1 -- 1000)
|
||||
|> S.flatMap (fun i -> S.(i -- (i+1)))
|
||||
|> S.length
|
||||
|> OUnit.assert_equal 2000
|
||||
|
||||
let test_intersperse () =
|
||||
1 -- 100
|
||||
S.(1 -- 100)
|
||||
|> (fun seq -> S.intersperse 0 seq)
|
||||
|> S.take 10
|
||||
|> S.to_list
|
||||
|
|
@ -98,7 +103,7 @@ let test_persistent () =
|
|||
|
||||
let test_big_persistent () =
|
||||
let printer = pp_ilist in
|
||||
let seq = 0 -- 10_000 in
|
||||
let seq = S.(0 -- 10_000) in
|
||||
let seq' = S.persistent seq in
|
||||
OUnit.assert_equal 10_001 (S.length seq');
|
||||
OUnit.assert_equal 10_001 (S.length seq');
|
||||
|
|
@ -106,7 +111,7 @@ let test_big_persistent () =
|
|||
()
|
||||
|
||||
let test_sort () =
|
||||
1 -- 100
|
||||
S.(1 -- 100)
|
||||
|> S.sort ~cmp:(fun i j -> j - i)
|
||||
|> S.take 4
|
||||
|> S.to_list
|
||||
|
|
@ -115,18 +120,18 @@ let test_sort () =
|
|||
let test_sort_uniq () =
|
||||
[42;1;2;3;4;5;4;3;2;1]
|
||||
|> S.of_list
|
||||
|> S.sort_uniq
|
||||
|> S.sort_uniq ?cmp:None
|
||||
|> S.to_list
|
||||
|> OUnit.assert_equal [1;2;3;4;5;42]
|
||||
|
||||
let test_group () =
|
||||
[1;2;3;3;2;2;3;4]
|
||||
|> S.of_list |> S.group |> S.to_list
|
||||
|> S.of_list |> S.group ?eq:None |> S.to_list
|
||||
|> OUnit.assert_equal [[1];[2];[3;3];[2;2];[3];[4]]
|
||||
|
||||
let test_uniq () =
|
||||
[1;2;2;3;4;4;4;3;3]
|
||||
|> S.of_list |> S.uniq |> S.to_list
|
||||
|> S.of_list |> S.uniq ?eq:None |> S.to_list
|
||||
|> OUnit.assert_equal [1;2;3;4;3]
|
||||
|
||||
let test_product () =
|
||||
|
|
@ -140,7 +145,7 @@ let test_product () =
|
|||
"c",0; "c", 1; "c", 2;] s
|
||||
|
||||
let test_join () =
|
||||
let s1 = (1 -- 3) in
|
||||
let s1 = S.(1 -- 3) in
|
||||
let s2 = S.of_list ["1"; "2"] in
|
||||
let join_row i j =
|
||||
if string_of_int i = j then Some (string_of_int i ^ " = " ^ j) else None
|
||||
|
|
@ -150,16 +155,16 @@ let test_join () =
|
|||
()
|
||||
|
||||
let test_scan () =
|
||||
1 -- 5
|
||||
S.(1 -- 5)
|
||||
|> S.scan (+) 0
|
||||
|> S.to_list
|
||||
|> OUnit.assert_equal ~printer:pp_ilist [0;1;3;6;10;15]
|
||||
|
||||
let test_drop () =
|
||||
1 -- 5 |> S.drop 2 |> S.to_list |> OUnit.assert_equal [3;4;5]
|
||||
S.(1 -- 5) |> S.drop 2 |> S.to_list |> OUnit.assert_equal [3;4;5]
|
||||
|
||||
let test_rev () =
|
||||
1 -- 5 |> S.rev |> S.to_list |> OUnit.assert_equal [5;4;3;2;1]
|
||||
S.(1 -- 5) |> S.rev |> S.to_list |> OUnit.assert_equal [5;4;3;2;1]
|
||||
|
||||
let test_unfoldr () =
|
||||
let f x = if x < 5 then Some (string_of_int x,x+1) else None in
|
||||
|
|
@ -168,12 +173,12 @@ let test_unfoldr () =
|
|||
|> OUnit.assert_equal ["0"; "1"; "2"; "3"; "4"]
|
||||
|
||||
let test_hashtbl () =
|
||||
let h = 1 -- 5
|
||||
let h = S.(1 -- 5)
|
||||
|> S.zip_i
|
||||
|> S.to_hashtbl2 in
|
||||
0 -- 4
|
||||
S.(0 -- 4)
|
||||
|> S.iter (fun i -> OUnit.assert_equal (i+1) (Hashtbl.find h i));
|
||||
OUnit.assert_equal [0;1;2;3;4] (S.hashtbl_keys h |> S.sort |> S.to_list);
|
||||
OUnit.assert_equal [0;1;2;3;4] (S.hashtbl_keys h |> S.sort ?cmp:None |> S.to_list);
|
||||
()
|
||||
|
||||
let test_buff () =
|
||||
|
|
@ -208,6 +213,7 @@ let suite =
|
|||
[ "test_empty" >:: test_empty;
|
||||
"test_repeat" >:: test_repeat;
|
||||
"test_concat" >:: test_concat;
|
||||
"test_concat2" >:: test_concat2;
|
||||
"test_fold" >:: test_fold;
|
||||
"test_foldi" >:: test_foldi;
|
||||
"test_exists" >:: test_exists;
|
||||
|
|
@ -231,5 +237,5 @@ let suite =
|
|||
"test_hashtbl" >:: test_hashtbl;
|
||||
"test_int_range" >:: test_int_range;
|
||||
"test_take" >:: test_take;
|
||||
"test_regression1" >:: test_regression1
|
||||
"test_regression1" >:: test_regression1;
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue