Merge branch 'master' into stable for 0.9; oasis setup

This commit is contained in:
Simon Cruanes 2016-12-26 01:23:30 +01:00
commit c63104506c
14 changed files with 4900 additions and 4632 deletions

View file

@ -1,9 +1,10 @@
S . S src
S bench/ S bench/
S tests/ S tests/
B _build B _build/src
B _build/tests/ B _build/tests/
B _build/bench/ B _build/bench/
PKG oUnit PKG oUnit qcheck
PKG benchmark PKG benchmark
FLAG -safe-string FLG -safe-string
FLG -w +a -w -4 -w -44

View file

@ -94,4 +94,10 @@ release:
@read @read
opam publish submit $(NAME_VERSION) opam publish submit $(NAME_VERSION)
.PHONY: benchs tests examples update_next_tag push_doc push_stable watch:
while find src/ -print0 | xargs -0 inotifywait -e delete_self -e modify ; do \
echo "============ at `date` ==========" ; \
make all; \
done
.PHONY: benchs tests examples update_next_tag push_doc push_stable watch

197
README.adoc Normal file
View file

@ -0,0 +1,197 @@
= Sequence
:toc: macro
:source-highlighter: pygments
Simple sequence abstract datatype, intended to iterate efficiently
on collections while performing some transformations.
Common operations supported by Sequence include
`filter`, `map`, `take`, `drop`, `append`, `flat_map`, etc.
Sequence is not designed to be as general-purpose or flexible as, say,
Batteries' `'a Enum.t`. Rather, it aims at providing a very simple and efficient
way of iterating on a finite number of values, only allocating (most of the time)
one intermediate closure to do so. For instance, iterating on keys, or values,
of a `Hashtbl.t`, without creating a list.
== Documentation
There is only one important type, `'a Sequence.t`, and lots of functions built
around this type.
To get an overview of sequence, its origins and why it was created,
you can start with http://cedeela.fr/~simon/talks/sequence.pdf[the slides of a talk]
I (@c-cube) made at some OCaml meeting.
See https://c-cube.github.io/sequence/api/[the online API]
for more details on the set of available functions.
== Build
1. via opam `opam install sequence`
2. manually (need OCaml >= 3.12): `make all install`
If you have https://github.com/vincent-hugot/iTeML[qtest] installed,
you can build and run tests with
----
$ ./configure --enable-tests
$ make test
----
If you have https://github.com/Chris00/ocaml-benchmark[benchmarks] installed,
you can build and run benchmarks with
----
$ make benchs
$ ./benchs.native
----
To see how to use the library, check the `examples` directory.
`tests.ml` has a few examples of how to convert basic data structures into
sequences, and conversely.
== Short Tutorial
=== Transferring Data
Conversion between n container types
would take n² functions. In practice, for a given collection
we can at best hope for `to_list` and `of_list`.
With sequence, if the source structure provides a
`iter` function (or a `to_seq` wrapper), it becomes:
[source,OCaml]
----
# let q = Queue.create();;
# Sequence.( 1 -- 10 |> to_queue q);;
- : unit = ()
# Sequence.of_queue q |> Sequence.to_list ;;
- : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
# let s = Stack.create();;
# Sequence.(of_queue q |> to_stack s);;
- : unit = ()
# Sequence.of_stack s |> Sequence.to_list ;;
- : int list = [10; 9; 8; 7; 6; 5; 4; 3; 2; 1]
----
Note how the list of elements is reversed when we transfer them
from the queue to the stack.
Another example is extracting the list of values of
a hashtable (in an undefined order that depends on the
underlying hash function):
[source,OCaml]
----
# let h = Hashtbl.create 16;;
# for i = 0 to 10 do
Hashtbl.add h i (string_of_int i)
done;;
- : unit = ()
# Hashtbl.length h;;
- : int = 11
(* now to get the values *)
# Sequence.of_t
# Sequence.of_hashtbl h |> Sequence.map snd |> Sequence.to_list;;
- : string list = ["6"; "2"; "8"; "7"; "3"; "5"; "4"; "9"; "0"; "10"; "1"]
----
=== Replacing `for` loops
The `for` loop is a bit limited, and lacks compositionality.
Instead, it can be more convenient and readable to
use `Sequence.(--) : int -> int -> int Sequence.t`.
[source,OCaml]
----
# Sequence.(1 -- 10_000_000 |> fold (+) 0);;
- : int = 50000005000000
# let p x = x mod 5 = 0 in
Sequence.(1 -- 5_000
|> filter p
|> map (fun x -> x * x)
|> fold (+) 0
);;
- : int = 8345837500
----
NOTE: with **flambda** under sufficiently strong
optimization flags, such compositions of operators
will be compiled to an actual loop with no overhead!
=== Iterating on sub-trees
A small λ-calculus AST, and some operations on it.
[source,OCaml]
----
# type term =
| Var of string
| App of term * term
| Lambda of term ;;
# let rec subterms : term -> term Sequence.t =
fun t ->
let open Sequence.Infix in
Sequence.cons t
(match t with
| Var _ -> Sequence.empty
| Lambda u -> subterms u
| App (a,b) ->
Sequence.append (subterms a) (subterms b))
;;
(* Now we can define many other functions easily! *)
# let vars t =
Sequence.filter_map
(function Var s -> Some s | _ -> None)
(subterms t) ;;
val vars : term -> string sequence = <fun >
# let size t = Sequence.length (subterms t) ;;
val size : term -> int = <fun >
# let vars_list l = Sequence.(of_list l |> flat_map vars);;
val vars_list : term list -> string sequence = <fun >
----
=== Permutations
Makes it easy to write backtracking code (a non-deterministic
function returning several `'a`
will just return a `'a Sequence.t`).
Here, we generate all permutations of a list by
enumerating the ways we can insert an element in a list.
[source,OCaml]
----
# module S = Sequence ;;
# let rec insert x l = match l with
| [] -> S.return [x]
| y :: tl ->
S.append
S.(insert x tl >|= fun tl' -> y :: tl')
(S.return (x :: l)) ;;
# let rec permute l = match l with
| [] -> S.return []
| x :: tl -> permute tl >>= insert x ;;
# permute [1;2;3;4] |> S.take 2 |> S.to_list ;;
- : int list list = [[4; 3; 2; 1]; [4; 3; 1; 2]]
----
=== Advanced example
The module `examples/sexpr.mli` exposes the interface of the S-expression
example library. It requires OCaml>=4.0 to compile, because of the GADT
structure used in the monadic parser combinators part of `examples/sexpr.ml`.
Be careful that this is quite obscure.
== License
Sequence is available under the BSD license.

View file

@ -1,57 +0,0 @@
Sequence
========
Simple sequence abstract datatype, 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.
Sequence is not designed to be as general-purpose or flexible as, say,
Batteries' `Enum.t`. Rather, it aims at providing a very simple and efficient
way of iterating on a finite number of values, only allocating (most of the time)
one intermediate closure to do so. For instance, iterating on keys, or values,
of a `Hashtbl.t`, without creating a list.
Documentation
=============
There is only one type, `'a Sequence.t`, and lots of functions built around
this type.
To get an overview of sequence, its origins and why it was created,
you can start with [the slides of a talk](http://cedeela.fr/~simon/talks/sequence.pdf)
I (c-cube) made at some OCaml meeting.
See [the online API](http://cedeela.fr/~simon/software/sequence/Sequence.html)
for more details on the set of available functions.
Build
=====
1. via opam `opam install sequence`
2. manually (need OCaml >= 3.12): `make all install`
If you have `OUnit` installed, you can build and run tests with
$ make tests
$ ./run_tests.native
If you have `Bench` installed, you can build and run benchmarks with
$ make benchs
$ ./benchs.native
To see how to use the library, check the `examples` directory.
`tests.ml` has a few examples of how to convert basic data structures into
sequences, and conversely.
Examples
========
The module `examples/sexpr.mli` exposes the interface of the S-expression
example library. It requires OCaml>=4.0 to compile, because of the GADT
structure used in the monadic parser combinators part of `examples/sexpr.ml`.
License
=======
Sequence is available under the BSD license.

2
_oasis
View file

@ -1,6 +1,6 @@
OASISFormat: 0.4 OASISFormat: 0.4
Name: sequence Name: sequence
Version: 0.8 Version: 0.9
Homepage: https://github.com/c-cube/sequence Homepage: https://github.com/c-cube/sequence
Authors: Simon Cruanes Authors: Simon Cruanes
License: BSD-2-clause License: BSD-2-clause

View file

@ -10,10 +10,10 @@ let bench_fold n =
0 -- n |> S.fold (+) 0 |> ignore 0 -- n |> S.fold (+) 0 |> ignore
let bench_flatmap n = let bench_flatmap n =
0 -- n |> S.flatMap (fun i -> i -- (i+5)) |> (fun _ -> ()) 0 -- n |> S.flat_map (fun i -> i -- (i+5)) |> (fun _ -> ())
let bench_product n = let bench_product n =
S.product (0 -- n) (0 -- n) (fun (i,j) -> ()) S.product (0 -- n) (0 -- n) (fun _ -> ())
let _ = let _ =
List.iter List.iter

View file

@ -1,19 +1,12 @@
(* OASIS_START *) (* OASIS_START *)
(* DO NOT EDIT (digest: 8cefc2cf375bc79d721299976e7d0715) *) (* DO NOT EDIT (digest: 25607cca926d807aaffd1aa7d72d57d9) *)
module OASISGettext = struct module OASISGettext = struct
(* # 22 "src/oasis/OASISGettext.ml" *) (* # 22 "src/oasis/OASISGettext.ml" *)
let ns_ str = let ns_ str = str
str let s_ str = str
let f_ (str: ('a, 'b, 'c, 'd) format4) = str
let s_ str =
str
let f_ (str: ('a, 'b, 'c, 'd) format4) =
str
let fn_ fmt1 fmt2 n = let fn_ fmt1 fmt2 n =
@ -23,10 +16,7 @@ module OASISGettext = struct
fmt2^^"" fmt2^^""
let init = let init = []
[]
end end
module OASISString = struct module OASISString = struct
@ -38,7 +28,7 @@ module OASISString = struct
Mostly inspired by extlib and batteries ExtString and BatString libraries. Mostly inspired by extlib and batteries ExtString and BatString libraries.
@author Sylvain Le Gall @author Sylvain Le Gall
*) *)
let nsplitf str f = let nsplitf str f =
@ -52,19 +42,19 @@ module OASISString = struct
Buffer.clear buf Buffer.clear buf
in in
let str_len = String.length str in let str_len = String.length str in
for i = 0 to str_len - 1 do for i = 0 to str_len - 1 do
if f str.[i] then if f str.[i] then
push () push ()
else else
Buffer.add_char buf str.[i] Buffer.add_char buf str.[i]
done; done;
push (); push ();
List.rev !lst List.rev !lst
(** [nsplit c s] Split the string [s] at char [c]. It doesn't include the (** [nsplit c s] Split the string [s] at char [c]. It doesn't include the
separator. separator.
*) *)
let nsplit str c = let nsplit str c =
nsplitf str ((=) c) nsplitf str ((=) c)
@ -72,18 +62,18 @@ module OASISString = struct
let find ~what ?(offset=0) str = let find ~what ?(offset=0) str =
let what_idx = ref 0 in let what_idx = ref 0 in
let str_idx = ref offset in let str_idx = ref offset in
while !str_idx < String.length str && while !str_idx < String.length str &&
!what_idx < String.length what do !what_idx < String.length what do
if str.[!str_idx] = what.[!what_idx] then if str.[!str_idx] = what.[!what_idx] then
incr what_idx incr what_idx
else
what_idx := 0;
incr str_idx
done;
if !what_idx <> String.length what then
raise Not_found
else else
!str_idx - !what_idx what_idx := 0;
incr str_idx
done;
if !what_idx <> String.length what then
raise Not_found
else
!str_idx - !what_idx
let sub_start str len = let sub_start str len =
@ -106,19 +96,19 @@ module OASISString = struct
let what_idx = ref 0 in let what_idx = ref 0 in
let str_idx = ref offset in let str_idx = ref offset in
let ok = ref true in let ok = ref true in
while !ok && while !ok &&
!str_idx < String.length str && !str_idx < String.length str &&
!what_idx < String.length what do !what_idx < String.length what do
if str.[!str_idx] = what.[!what_idx] then if str.[!str_idx] = what.[!what_idx] then
incr what_idx incr what_idx
else
ok := false;
incr str_idx
done;
if !what_idx = String.length what then
true
else else
false ok := false;
incr str_idx
done;
if !what_idx = String.length what then
true
else
false
let strip_starts_with ~what str = let strip_starts_with ~what str =
@ -132,19 +122,19 @@ module OASISString = struct
let what_idx = ref ((String.length what) - 1) in let what_idx = ref ((String.length what) - 1) in
let str_idx = ref ((String.length str) - 1) in let str_idx = ref ((String.length str) - 1) in
let ok = ref true in let ok = ref true in
while !ok && while !ok &&
offset <= !str_idx && offset <= !str_idx &&
0 <= !what_idx do 0 <= !what_idx do
if str.[!str_idx] = what.[!what_idx] then if str.[!str_idx] = what.[!what_idx] then
decr what_idx decr what_idx
else
ok := false;
decr str_idx
done;
if !what_idx = -1 then
true
else else
false ok := false;
decr str_idx
done;
if !what_idx = -1 then
true
else
false
let strip_ends_with ~what str = let strip_ends_with ~what str =
@ -189,19 +179,181 @@ module OASISString = struct
end end
module OASISExpr = struct module OASISUtils = struct
(* # 22 "src/oasis/OASISExpr.ml" *) (* # 22 "src/oasis/OASISUtils.ml" *)
open OASISGettext open OASISGettext
module MapExt =
struct
module type S =
sig
include Map.S
val add_list: 'a t -> (key * 'a) list -> 'a t
val of_list: (key * 'a) list -> 'a t
val to_list: 'a t -> (key * 'a) list
end
module Make (Ord: Map.OrderedType) =
struct
include Map.Make(Ord)
let rec add_list t =
function
| (k, v) :: tl -> add_list (add k v t) tl
| [] -> t
let of_list lst = add_list empty lst
let to_list t = fold (fun k v acc -> (k, v) :: acc) t []
end
end
module MapString = MapExt.Make(String)
module SetExt =
struct
module type S =
sig
include Set.S
val add_list: t -> elt list -> t
val of_list: elt list -> t
val to_list: t -> elt list
end
module Make (Ord: Set.OrderedType) =
struct
include Set.Make(Ord)
let rec add_list t =
function
| e :: tl -> add_list (add e t) tl
| [] -> t
let of_list lst = add_list empty lst
let to_list = elements
end
end
module SetString = SetExt.Make(String)
let compare_csl s1 s2 =
String.compare (OASISString.lowercase_ascii s1) (OASISString.lowercase_ascii s2)
module HashStringCsl =
Hashtbl.Make
(struct
type t = string
let equal s1 s2 = (compare_csl s1 s2) = 0
let hash s = Hashtbl.hash (OASISString.lowercase_ascii s)
end)
module SetStringCsl =
SetExt.Make
(struct
type t = string
let compare = compare_csl
end)
let varname_of_string ?(hyphen='_') s =
if String.length s = 0 then
begin
invalid_arg "varname_of_string"
end
else
begin
let buf =
OASISString.replace_chars
(fun c ->
if ('a' <= c && c <= 'z')
||
('A' <= c && c <= 'Z')
||
('0' <= c && c <= '9') then
c
else
hyphen)
s;
in
let buf =
(* Start with a _ if digit *)
if '0' <= s.[0] && s.[0] <= '9' then
"_"^buf
else
buf
in
OASISString.lowercase_ascii buf
end
let varname_concat ?(hyphen='_') p s =
let what = String.make 1 hyphen in
let p =
try
OASISString.strip_ends_with ~what p
with Not_found ->
p
in
let s =
try
OASISString.strip_starts_with ~what s
with Not_found ->
s
in
p^what^s
let is_varname str =
str = varname_of_string str
let failwithf fmt = Printf.ksprintf failwith fmt
let rec file_location ?pos1 ?pos2 ?lexbuf () =
match pos1, pos2, lexbuf with
| Some p, None, _ | None, Some p, _ ->
file_location ~pos1:p ~pos2:p ?lexbuf ()
| Some p1, Some p2, _ ->
let open Lexing in
let fn, lineno = p1.pos_fname, p1.pos_lnum in
let c1 = p1.pos_cnum - p1.pos_bol in
let c2 = c1 + (p2.pos_cnum - p1.pos_cnum) in
Printf.sprintf (f_ "file %S, line %d, characters %d-%d") fn lineno c1 c2
| _, _, Some lexbuf ->
file_location
~pos1:(Lexing.lexeme_start_p lexbuf)
~pos2:(Lexing.lexeme_end_p lexbuf)
()
| None, None, None ->
s_ "<position undefined>"
let failwithpf ?pos1 ?pos2 ?lexbuf fmt =
let loc = file_location ?pos1 ?pos2 ?lexbuf () in
Printf.ksprintf (fun s -> failwith (Printf.sprintf "%s: %s" loc s)) fmt
end
module OASISExpr = struct
(* # 22 "src/oasis/OASISExpr.ml" *)
open OASISGettext
open OASISUtils
type test = string type test = string
type flag = string type flag = string
@ -214,7 +366,6 @@ module OASISExpr = struct
| ETest of test * string | ETest of test * string
type 'a choices = (t * 'a) list type 'a choices = (t * 'a) list
@ -289,7 +440,7 @@ module OASISExpr = struct
end end
# 292 "myocamlbuild.ml" # 443 "myocamlbuild.ml"
module BaseEnvLight = struct module BaseEnvLight = struct
(* # 22 "src/base/BaseEnvLight.ml" *) (* # 22 "src/base/BaseEnvLight.ml" *)
@ -300,132 +451,103 @@ module BaseEnvLight = struct
type t = string MapString.t type t = string MapString.t
let default_filename = let default_filename = Filename.concat (Sys.getcwd ()) "setup.data"
Filename.concat
(Sys.getcwd ())
"setup.data"
let load ?(allow_empty=false) ?(filename=default_filename) () = let load ?(allow_empty=false) ?(filename=default_filename) ?stream () =
if Sys.file_exists filename then let line = ref 1 in
begin let lexer st =
let chn = let st_line =
open_in_bin filename Stream.from
in (fun _ ->
let st = try
Stream.of_channel chn match Stream.next st with
in | '\n' -> incr line; Some '\n'
let line = | c -> Some c
ref 1 with Stream.Failure -> None)
in in
let st_line = Genlex.make_lexer ["="] st_line
Stream.from in
(fun _ -> let rec read_file lxr mp =
try match Stream.npeek 3 lxr with
match Stream.next st with | [Genlex.Ident nm; Genlex.Kwd "="; Genlex.String value] ->
| '\n' -> incr line; Some '\n' Stream.junk lxr; Stream.junk lxr; Stream.junk lxr;
| c -> Some c read_file lxr (MapString.add nm value mp)
with Stream.Failure -> None) | [] -> mp
in | _ ->
let lexer = failwith
Genlex.make_lexer ["="] st_line (Printf.sprintf "Malformed data file '%s' line %d" filename !line)
in in
let rec read_file mp = match stream with
match Stream.npeek 3 lexer with | Some st -> read_file (lexer st) MapString.empty
| [Genlex.Ident nm; Genlex.Kwd "="; Genlex.String value] -> | None ->
Stream.junk lexer; if Sys.file_exists filename then begin
Stream.junk lexer; let chn = open_in_bin filename in
Stream.junk lexer; let st = Stream.of_channel chn in
read_file (MapString.add nm value mp) try
| [] -> let mp = read_file (lexer st) MapString.empty in
mp close_in chn; mp
| _ -> with e ->
failwith close_in chn; raise e
(Printf.sprintf end else if allow_empty then begin
"Malformed data file '%s' line %d"
filename !line)
in
let mp =
read_file MapString.empty
in
close_in chn;
mp
end
else if allow_empty then
begin
MapString.empty MapString.empty
end end else begin
else
begin
failwith failwith
(Printf.sprintf (Printf.sprintf
"Unable to load environment, the file '%s' doesn't exist." "Unable to load environment, the file '%s' doesn't exist."
filename) filename)
end end
let rec var_expand str env = let rec var_expand str env =
let buff = let buff = Buffer.create ((String.length str) * 2) in
Buffer.create ((String.length str) * 2) Buffer.add_substitute
in buff
Buffer.add_substitute (fun var ->
buff try
(fun var -> var_expand (MapString.find var env) env
try with Not_found ->
var_expand (MapString.find var env) env failwith
with Not_found -> (Printf.sprintf
failwith "No variable %s defined when trying to expand %S."
(Printf.sprintf var
"No variable %s defined when trying to expand %S." str))
var str;
str)) Buffer.contents buff
str;
Buffer.contents buff
let var_get name env = let var_get name env = var_expand (MapString.find name env) env
var_expand (MapString.find name env) env let var_choose lst env = OASISExpr.choose (fun nm -> var_get nm env) lst
let var_choose lst env =
OASISExpr.choose
(fun nm -> var_get nm env)
lst
end end
# 397 "myocamlbuild.ml" # 523 "myocamlbuild.ml"
module MyOCamlbuildFindlib = struct module MyOCamlbuildFindlib = struct
(* # 22 "src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml" *) (* # 22 "src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml" *)
(** OCamlbuild extension, copied from (** OCamlbuild extension, copied from
* http://brion.inria.fr/gallium/index.php/Using_ocamlfind_with_ocamlbuild * https://ocaml.org/learn/tutorials/ocamlbuild/Using_ocamlfind_with_ocamlbuild.html
* by N. Pouillard and others * by N. Pouillard and others
* *
* Updated on 2009/02/28 * Updated on 2016-06-02
* *
* Modified by Sylvain Le Gall * Modified by Sylvain Le Gall
*) *)
open Ocamlbuild_plugin open Ocamlbuild_plugin
type conf =
{ no_automatic_syntax: bool;
}
(* these functions are not really officially exported *) type conf = {no_automatic_syntax: bool}
let run_and_read =
Ocamlbuild_pack.My_unix.run_and_read
let blank_sep_strings = let run_and_read = Ocamlbuild_pack.My_unix.run_and_read
Ocamlbuild_pack.Lexers.blank_sep_strings
let blank_sep_strings = Ocamlbuild_pack.Lexers.blank_sep_strings
let exec_from_conf exec = let exec_from_conf exec =
let exec = let exec =
let env_filename = Pathname.basename BaseEnvLight.default_filename in let env = BaseEnvLight.load ~allow_empty:true () in
let env = BaseEnvLight.load ~filename:env_filename ~allow_empty:true () in
try try
BaseEnvLight.var_get exec env BaseEnvLight.var_get exec env
with Not_found -> with Not_found ->
@ -436,7 +558,7 @@ module MyOCamlbuildFindlib = struct
if Sys.os_type = "Win32" then begin if Sys.os_type = "Win32" then begin
let buff = Buffer.create (String.length str) in let buff = Buffer.create (String.length str) in
(* Adapt for windowsi, ocamlbuild + win32 has a hard time to handle '\\'. (* Adapt for windowsi, ocamlbuild + win32 has a hard time to handle '\\'.
*) *)
String.iter String.iter
(fun c -> Buffer.add_char buff (if c = '\\' then '/' else c)) (fun c -> Buffer.add_char buff (if c = '\\' then '/' else c))
str; str;
@ -445,7 +567,8 @@ module MyOCamlbuildFindlib = struct
str str
end end
in in
fix_win32 exec fix_win32 exec
let split s ch = let split s ch =
let buf = Buffer.create 13 in let buf = Buffer.create 13 in
@ -454,15 +577,15 @@ module MyOCamlbuildFindlib = struct
x := (Buffer.contents buf) :: !x; x := (Buffer.contents buf) :: !x;
Buffer.clear buf Buffer.clear buf
in in
String.iter String.iter
(fun c -> (fun c ->
if c = ch then if c = ch then
flush () flush ()
else else
Buffer.add_char buf c) Buffer.add_char buf c)
s; s;
flush (); flush ();
List.rev !x List.rev !x
let split_nl s = split s '\n' let split_nl s = split s '\n'
@ -504,85 +627,89 @@ module MyOCamlbuildFindlib = struct
let dispatch conf = let dispatch conf =
function function
| After_options -> | After_options ->
(* By using Before_options one let command line options have an higher (* By using Before_options one let command line options have an higher
* priority on the contrary using After_options will guarantee to have * priority on the contrary using After_options will guarantee to have
* the higher priority override default commands by ocamlfind ones *) * the higher priority override default commands by ocamlfind ones *)
Options.ocamlc := ocamlfind & A"ocamlc"; Options.ocamlc := ocamlfind & A"ocamlc";
Options.ocamlopt := ocamlfind & A"ocamlopt"; Options.ocamlopt := ocamlfind & A"ocamlopt";
Options.ocamldep := ocamlfind & A"ocamldep"; Options.ocamldep := ocamlfind & A"ocamldep";
Options.ocamldoc := ocamlfind & A"ocamldoc"; Options.ocamldoc := ocamlfind & A"ocamldoc";
Options.ocamlmktop := ocamlfind & A"ocamlmktop"; Options.ocamlmktop := ocamlfind & A"ocamlmktop";
Options.ocamlmklib := ocamlfind & A"ocamlmklib" Options.ocamlmklib := ocamlfind & A"ocamlmklib"
| After_rules -> | After_rules ->
(* When one link an OCaml library/binary/package, one should use (* Avoid warnings for unused tag *)
* -linkpkg *) flag ["tests"] N;
flag ["ocaml"; "link"; "program"] & A"-linkpkg";
if not (conf.no_automatic_syntax) then begin (* When one link an OCaml library/binary/package, one should use
(* For each ocamlfind package one inject the -package option when * -linkpkg *)
* compiling, computing dependencies, generating documentation and flag ["ocaml"; "link"; "program"] & A"-linkpkg";
* linking. *)
List.iter
begin fun pkg ->
let base_args = [A"-package"; A pkg] in
(* TODO: consider how to really choose camlp4o or camlp4r. *)
let syn_args = [A"-syntax"; A "camlp4o"] in
let (args, pargs) =
(* Heuristic to identify syntax extensions: whether they end in
".syntax"; some might not.
*)
if Filename.check_suffix pkg "syntax" ||
List.mem pkg well_known_syntax then
(syn_args @ base_args, syn_args)
else
(base_args, [])
in
flag ["ocaml"; "compile"; "pkg_"^pkg] & S args;
flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S args;
flag ["ocaml"; "doc"; "pkg_"^pkg] & S args;
flag ["ocaml"; "link"; "pkg_"^pkg] & S base_args;
flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S args;
(* TODO: Check if this is allowed for OCaml < 3.12.1 *) (* For each ocamlfind package one inject the -package option when
flag ["ocaml"; "compile"; "package("^pkg^")"] & S pargs; * compiling, computing dependencies, generating documentation and
flag ["ocaml"; "ocamldep"; "package("^pkg^")"] & S pargs; * linking. *)
flag ["ocaml"; "doc"; "package("^pkg^")"] & S pargs; List.iter
flag ["ocaml"; "infer_interface"; "package("^pkg^")"] & S pargs; begin fun pkg ->
end let base_args = [A"-package"; A pkg] in
(find_packages ()); (* TODO: consider how to really choose camlp4o or camlp4r. *)
end; let syn_args = [A"-syntax"; A "camlp4o"] in
let (args, pargs) =
(* Heuristic to identify syntax extensions: whether they end in
".syntax"; some might not.
*)
if not (conf.no_automatic_syntax) &&
(Filename.check_suffix pkg "syntax" ||
List.mem pkg well_known_syntax) then
(syn_args @ base_args, syn_args)
else
(base_args, [])
in
flag ["ocaml"; "compile"; "pkg_"^pkg] & S args;
flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S args;
flag ["ocaml"; "doc"; "pkg_"^pkg] & S args;
flag ["ocaml"; "link"; "pkg_"^pkg] & S base_args;
flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S args;
(* Like -package but for extensions syntax. Morover -syntax is useless (* TODO: Check if this is allowed for OCaml < 3.12.1 *)
* when linking. *) flag ["ocaml"; "compile"; "package("^pkg^")"] & S pargs;
List.iter begin fun syntax -> flag ["ocaml"; "ocamldep"; "package("^pkg^")"] & S pargs;
flag ["ocaml"; "doc"; "package("^pkg^")"] & S pargs;
flag ["ocaml"; "infer_interface"; "package("^pkg^")"] & S pargs;
end
(find_packages ());
(* Like -package but for extensions syntax. Morover -syntax is useless
* when linking. *)
List.iter begin fun syntax ->
flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
flag ["ocaml"; "infer_interface"; "syntax_"^syntax] & flag ["ocaml"; "infer_interface"; "syntax_"^syntax] &
S[A"-syntax"; A syntax]; S[A"-syntax"; A syntax];
end (find_syntaxes ()); end (find_syntaxes ());
(* The default "thread" tag is not compatible with ocamlfind. (* The default "thread" tag is not compatible with ocamlfind.
* Indeed, the default rules add the "threads.cma" or "threads.cmxa" * Indeed, the default rules add the "threads.cma" or "threads.cmxa"
* options when using this tag. When using the "-linkpkg" option with * options when using this tag. When using the "-linkpkg" option with
* ocamlfind, this module will then be added twice on the command line. * ocamlfind, this module will then be added twice on the command line.
* *
* To solve this, one approach is to add the "-thread" option when using * To solve this, one approach is to add the "-thread" option when using
* the "threads" package using the previous plugin. * the "threads" package using the previous plugin.
*) *)
flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]); flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]);
flag ["ocaml"; "pkg_threads"; "doc"] (S[A "-I"; A "+threads"]); flag ["ocaml"; "pkg_threads"; "doc"] (S[A "-I"; A "+threads"]);
flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]); flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]);
flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"]); flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"]);
flag ["ocaml"; "package(threads)"; "compile"] (S[A "-thread"]); flag ["c"; "pkg_threads"; "compile"] (S[A "-thread"]);
flag ["ocaml"; "package(threads)"; "doc"] (S[A "-I"; A "+threads"]); flag ["ocaml"; "package(threads)"; "compile"] (S[A "-thread"]);
flag ["ocaml"; "package(threads)"; "link"] (S[A "-thread"]); flag ["ocaml"; "package(threads)"; "doc"] (S[A "-I"; A "+threads"]);
flag ["ocaml"; "package(threads)"; "infer_interface"] (S[A "-thread"]); flag ["ocaml"; "package(threads)"; "link"] (S[A "-thread"]);
flag ["ocaml"; "package(threads)"; "infer_interface"] (S[A "-thread"]);
flag ["c"; "package(threads)"; "compile"] (S[A "-thread"]);
| _ -> | _ ->
() ()
end end
module MyOCamlbuildBase = struct module MyOCamlbuildBase = struct
@ -594,9 +721,6 @@ module MyOCamlbuildBase = struct
*) *)
open Ocamlbuild_plugin open Ocamlbuild_plugin
module OC = Ocamlbuild_pack.Ocaml_compiler module OC = Ocamlbuild_pack.Ocaml_compiler
@ -607,9 +731,6 @@ module MyOCamlbuildBase = struct
type tag = string type tag = string
(* # 62 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
type t = type t =
{ {
lib_ocaml: (name * dir list * string list) list; lib_ocaml: (name * dir list * string list) list;
@ -622,9 +743,10 @@ module MyOCamlbuildBase = struct
} }
let env_filename = (* # 110 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
Pathname.basename
BaseEnvLight.default_filename
let env_filename = Pathname.basename BaseEnvLight.default_filename
let dispatch_combine lst = let dispatch_combine lst =
@ -643,12 +765,7 @@ module MyOCamlbuildBase = struct
let dispatch t e = let dispatch t e =
let env = let env = BaseEnvLight.load ~allow_empty:true () in
BaseEnvLight.load
~filename:env_filename
~allow_empty:true
()
in
match e with match e with
| Before_options -> | Before_options ->
let no_trailing_dot s = let no_trailing_dot s =
@ -712,18 +829,19 @@ module MyOCamlbuildBase = struct
flag ["link"; "library"; "ocaml"; "native"; tag_libstubs lib] flag ["link"; "library"; "ocaml"; "native"; tag_libstubs lib]
(S[A"-cclib"; A("-l"^(nm_libstubs lib))]); (S[A"-cclib"; A("-l"^(nm_libstubs lib))]);
flag ["link"; "program"; "ocaml"; "byte"; tag_libstubs lib] if bool_of_string (BaseEnvLight.var_get "native_dynlink" env) then
(S[A"-dllib"; A("dll"^(nm_libstubs lib))]); flag ["link"; "program"; "ocaml"; "byte"; tag_libstubs lib]
(S[A"-dllib"; A("dll"^(nm_libstubs lib))]);
(* When ocaml link something that use the C library, then one (* When ocaml link something that use the C library, then one
need that file to be up to date. need that file to be up to date.
This holds both for programs and for libraries. This holds both for programs and for libraries.
*) *)
dep ["link"; "ocaml"; tag_libstubs lib] dep ["link"; "ocaml"; tag_libstubs lib]
[dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)]; [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
dep ["compile"; "ocaml"; tag_libstubs lib] dep ["compile"; "ocaml"; tag_libstubs lib]
[dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)]; [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
(* TODO: be more specific about what depends on headers *) (* TODO: be more specific about what depends on headers *)
(* Depends on .h files *) (* Depends on .h files *)
@ -763,7 +881,7 @@ module MyOCamlbuildBase = struct
end end
# 766 "myocamlbuild.ml" # 884 "myocamlbuild.ml"
open Ocamlbuild_plugin;; open Ocamlbuild_plugin;;
let package_default = let package_default =
{ {
@ -789,6 +907,6 @@ let conf = {MyOCamlbuildFindlib.no_automatic_syntax = false}
let dispatch_default = MyOCamlbuildBase.dispatch_default conf package_default;; let dispatch_default = MyOCamlbuildBase.dispatch_default conf package_default;;
# 793 "myocamlbuild.ml" # 911 "myocamlbuild.ml"
(* OASIS_STOP *) (* OASIS_STOP *)
Ocamlbuild_plugin.dispatch dispatch_default;; Ocamlbuild_plugin.dispatch dispatch_default;;

2
opam
View file

@ -1,6 +1,6 @@
opam-version: "1.2" opam-version: "1.2"
name: "sequence" name: "sequence"
version: "0.8" version: "0.9"
author: "Simon Cruanes" author: "Simon Cruanes"
maintainer: "simon.cruanes@inria.fr" maintainer: "simon.cruanes@inria.fr"
license: "BSD-2-clauses" license: "BSD-2-clauses"

7259
setup.ml

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
# OASIS_START # OASIS_START
# DO NOT EDIT (digest: 8041ba3970fcecd2b690dc7b78ccae41) # DO NOT EDIT (digest: b247543864e9cc39f327533c7e23c440)
version = "0.7" version = "0.9"
description = "Simple sequence (iterator) datatype and combinators" description = "Simple sequence (iterator) datatype and combinators"
requires = "bytes" requires = "bytes"
archive(byte) = "sequence.cma" archive(byte) = "sequence.cma"
@ -9,7 +9,7 @@ archive(native) = "sequence.cmxa"
archive(native, plugin) = "sequence.cmxs" archive(native, plugin) = "sequence.cmxs"
exists_if = "sequence.cma" exists_if = "sequence.cma"
package "invert" ( package "invert" (
version = "0.7" version = "0.9"
description = "Simple sequence (iterator) datatype and combinators" description = "Simple sequence (iterator) datatype and combinators"
requires = "sequence delimcc" requires = "sequence delimcc"
archive(byte) = "invert.cma" archive(byte) = "invert.cma"
@ -20,7 +20,7 @@ package "invert" (
) )
package "bigarray" ( package "bigarray" (
version = "0.7" version = "0.9"
description = "Simple sequence (iterator) datatype and combinators" description = "Simple sequence (iterator) datatype and combinators"
requires = "sequence bigarray" requires = "sequence bigarray"
archive(byte) = "bigarray.cma" archive(byte) = "bigarray.cma"

View file

@ -48,6 +48,17 @@ let repeat x k = while true do k x done
(seq |> take 3 |> to_list); (seq |> take 3 |> to_list);
*) *)
let init f yield =
let rec aux i =
yield (f i);
aux (i+1)
in
aux 0
(*$=
[0;1;2;3;4] (init (fun x->x) |> take 5 |> to_list)
*)
let rec iterate f x k = let rec iterate f x k =
k x; k x;
iterate f (f x) k iterate f (f x) k
@ -94,6 +105,28 @@ let foldi f init seq =
OUnit.assert_equal [1, "world"; 0, "hello"] l; OUnit.assert_equal [1, "world"; 0, "hello"] l;
*) *)
let fold_map f init seq yield =
let r = ref init in
seq
(fun x ->
let acc', y = f !r x in
r := acc';
yield y)
(*$= & ~printer:Q.Print.(list int)
[0;1;3;5] (0--3 |> fold_map (fun prev x -> x,prev+x) 0 |> to_list)
*)
let fold_filter_map f init seq yield =
let r = ref init in
seq
(fun x ->
let acc', y = f !r x in
r := acc';
match y with
| None -> ()
| Some y' -> yield y')
let map f seq k = seq (fun x -> k (f x)) let map f seq k = seq (fun x -> k (f x))
let mapi f seq k = let mapi f seq k =
@ -133,9 +166,7 @@ let concat s k = s (fun s' -> s' k)
let flatten s = concat s let flatten s = concat s
let flatMap f seq k = seq (fun x -> f x k) let flat_map f seq k = seq (fun x -> f x k)
let flat_map = flatMap
(*$R (*$R
(1 -- 1000) (1 -- 1000)
@ -147,14 +178,12 @@ let flat_map = flatMap
let flat_map_l f seq k = let flat_map_l f seq k =
seq (fun x -> List.iter k (f x)) seq (fun x -> List.iter k (f x))
let fmap f seq k = let filter_map f seq k =
seq (fun x -> match f x with seq (fun x -> match f x with
| None -> () | None -> ()
| Some y -> k y | Some y -> k y
) )
let filter_map = fmap
let intersperse elem seq k = let intersperse elem seq k =
let first = ref true in let first = ref true in
seq (fun x -> (if !first then first := false else k elem); k x) seq (fun x -> (if !first then first := false else k elem); k x)
@ -324,6 +353,23 @@ let sort ?(cmp=Pervasives.compare) seq =
|> OUnit.assert_equal [100;99;98;97] |> OUnit.assert_equal [100;99;98;97]
*) *)
exception Exit_sorted
let sorted ?(cmp=Pervasives.compare) seq =
let prev = ref None in
try
seq (fun x -> match !prev with
| Some y when cmp y x > 0 -> raise Exit_sorted
| _ -> prev := Some x);
true
with Exit_sorted -> false
(*$T
of_list [1;2;3;4] |> sorted
not (of_list [1;2;3;0;4] |> sorted)
sorted empty
*)
let group_succ_by ?(eq=fun x y -> x = y) seq k = let group_succ_by ?(eq=fun x y -> x = y) seq k =
let cur = ref [] in let cur = ref [] in
seq (fun x -> seq (fun x ->
@ -337,8 +383,6 @@ let group_succ_by ?(eq=fun x y -> x = y) seq k =
(* last list *) (* last list *)
if !cur <> [] then k !cur if !cur <> [] then k !cur
let group = group_succ_by
(*$R (*$R
[1;2;3;3;2;2;3;4] [1;2;3;3;2;2;3;4]
|> of_list |> group_succ_by ?eq:None |> to_list |> of_list |> group_succ_by ?eq:None |> to_list
@ -419,6 +463,25 @@ let product outer inner k =
let product2 outer inner k = let product2 outer inner k =
outer (fun x -> inner (fun y -> k x y)) outer (fun x -> inner (fun y -> k x y))
let rec diagonal_l l yield = match l with
| [] -> ()
| x::tail ->
List.iter (fun y -> yield (x,y)) tail;
diagonal_l tail yield
(*$=
[0,1; 0,2; 1,2] (diagonal_l [0;1;2] |> to_list)
*)
let diagonal seq =
let l = ref [] in
seq (fun x -> l := x :: !l);
diagonal_l (List.rev !l)
(*$=
[0,1; 0,2; 1,2] (of_list [0;1;2] |> diagonal |> to_list)
*)
let join ~join_row s1 s2 k = let join ~join_row s1 s2 k =
s1 (fun a -> s1 (fun a ->
s2 (fun b -> s2 (fun b ->
@ -613,6 +676,25 @@ let find f seq =
end; end;
!r !r
let findi f seq =
let i = ref 0 in
let r = ref None in
begin
try
seq
(fun x -> match f !i x with
| None -> incr i
| Some _ as res -> r := res; raise ExitFind);
with ExitFind -> ()
end;
!r
let find_pred f seq = find (fun x -> if f x then Some x else None) seq
let find_pred_exn f seq = match find_pred f seq with
| Some x -> x
| None -> raise Not_found
let length seq = let length seq =
let r = ref 0 in let r = ref 0 in
seq (fun _ -> incr r); seq (fun _ -> incr r);

View file

@ -57,6 +57,10 @@ val singleton : 'a -> 'a t
val doubleton : 'a -> 'a -> 'a t val doubleton : 'a -> 'a -> 'a t
(** Sequence with exactly two elements *) (** Sequence with exactly two elements *)
val init : (int -> 'a) -> 'a t
(** [init f] is the infinite sequence [f 0; f 1; f 2; …].
@since 0.9 *)
val cons : 'a -> 'a t -> 'a t val cons : 'a -> 'a t -> 'a t
(** [cons x l] yields [x], then yields from [l]. (** [cons x l] yields [x], then yields from [l].
Same as [append (singleton x) l] *) Same as [append (singleton x) l] *)
@ -103,6 +107,17 @@ val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a
(** Fold over elements of the sequence and their index, consuming it *) (** Fold over elements of the sequence and their index, consuming it *)
val fold_map : ('acc -> 'a -> 'acc * 'b) -> 'acc -> 'a t -> 'b t
(** [fold_map f acc l] is like {!map}, but it carries some state as in
{!fold}. The state is not returned, it is just used to thread some
information to the map function.
@since 0.9 *)
val fold_filter_map : ('acc -> 'a -> 'acc * 'b option) -> 'acc -> 'a t -> 'b t
(** [fold_filter_map f acc l] is a {!fold_map}-like function, but the
function can choose to skip an element by retuning [None].
@since 0.9 *)
val map : ('a -> 'b) -> 'a t -> 'b t val map : ('a -> 'b) -> 'a t -> 'b t
(** Map objects of the sequence into other elements, lazily *) (** Map objects of the sequence into other elements, lazily *)
@ -129,6 +144,20 @@ val find : ('a -> 'b option) -> 'a t -> 'b option
(** Find the first element on which the function doesn't return [None] (** Find the first element on which the function doesn't return [None]
@since 0.5 *) @since 0.5 *)
val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option
(** Indexed version of {!find}
@since 0.9 *)
val find_pred : ('a -> bool) -> 'a t -> 'a option
(** [find_pred p l] finds the first element of [l] that satisfies [p],
or returns [None] if no element satisfies [p]
@since 0.9 *)
val find_pred_exn : ('a -> bool) -> 'a t -> 'a
(** Unsafe version of {!find_pred}
@raise Not_found if no such element is found
@since 0.9 *)
val length : 'a t -> int val length : 'a t -> int
(** How long is the sequence? Forces the sequence. *) (** How long is the sequence? Forces the sequence. *)
@ -150,23 +179,19 @@ val concat : 'a t t -> 'a t
val flatten : 'a t t -> 'a t val flatten : 'a t t -> 'a t
(** Alias for {!concat} *) (** Alias for {!concat} *)
val flatMap : ('a -> 'b t) -> 'a t -> 'b t
(** @deprecated use {!flat_map} since 0.6 *)
val flat_map : ('a -> 'b t) -> 'a t -> 'b t val flat_map : ('a -> 'b t) -> 'a t -> 'b t
(** Monadic bind. Intuitively, it applies the function to every (** Monadic bind. Intuitively, it applies the function to every
element of the initial sequence, and calls {!concat}. element of the initial sequence, and calls {!concat}.
Formerly [flatMap]
@since 0.5 *) @since 0.5 *)
val flat_map_l : ('a -> 'b list) -> 'a t -> 'b t val flat_map_l : ('a -> 'b list) -> 'a t -> 'b t
(** Convenience function combining {!flat_map} and {!of_list} (** Convenience function combining {!flat_map} and {!of_list}
@since 0.8 *) @since 0.8 *)
val fmap : ('a -> 'b option) -> 'a t -> 'b t
(** @deprecated use {!filter_map} since 0.6 *)
val filter_map : ('a -> 'b option) -> 'a t -> 'b t val filter_map : ('a -> 'b option) -> 'a t -> 'b t
(** Map and only keep non-[None] elements (** Map and only keep non-[None] elements
Formerly [fmap]
@since 0.5 *) @since 0.5 *)
val intersperse : 'a -> 'a t -> 'a t val intersperse : 'a -> 'a t -> 'a t
@ -201,13 +226,13 @@ val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
(** Sort the sequence and remove duplicates. Eager, same as [sort] *) (** Sort the sequence and remove duplicates. Eager, same as [sort] *)
val group : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t val sorted : ?cmp:('a -> 'a -> int) -> 'a t -> bool
(** Group equal consecutive elements. (** Checks whether the sequence is sorted. Eager, same as {!sort}.
@deprecated since 0.6 use {!group_succ_by} *) @since 0.9 *)
val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t
(** Group equal consecutive elements. (** Group equal consecutive elements.
Synonym to {!group}. Formerly synonym to [group].
@since 0.6 *) @since 0.6 *)
val group_by : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> val group_by : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) ->
@ -226,6 +251,16 @@ val product : 'a t -> 'b t -> ('a * 'b) t
as required (several times), possibly by calling {!persistent} on it as required (several times), possibly by calling {!persistent} on it
beforehand. *) beforehand. *)
val diagonal_l : 'a list -> ('a * 'a) t
(** All pairs of distinct positions of the list. [diagonal l] will
return the sequence of all [List.nth i l, List.nth j l] if [i < j].
@since 0.9 *)
val diagonal : 'a t -> ('a * 'a) t
(** All pairs of distinct positions of the sequence.
Iterates only once on the sequence, which must be finite.
@since 0.9 *)
val product2 : 'a t -> 'b t -> ('a, 'b) t2 val product2 : 'a t -> 'b t -> ('a, 'b) t2
(** Binary version of {!product}. Same requirements. (** Binary version of {!product}. Same requirements.
@since 0.5 *) @since 0.5 *)

File diff suppressed because it is too large Load diff

1
src/sequenceLabels.ml Symbolic link
View file

@ -0,0 +1 @@
sequence.ml

View file

@ -35,6 +35,10 @@ val singleton : 'a -> 'a t
val doubleton : 'a -> 'a -> 'a t val doubleton : 'a -> 'a -> 'a t
(** Sequence with exactly two elements *) (** Sequence with exactly two elements *)
val init : f:(int -> 'a) -> 'a t
(** [init f] is the infinite sequence [f 0; f 1; f 2; …].
@since 0.9 *)
val cons : 'a -> 'a t -> 'a t val cons : 'a -> 'a t -> 'a t
(** [cons x l] yields [x], then yields from [l]. (** [cons x l] yields [x], then yields from [l].
Same as [append (singleton x) l] *) Same as [append (singleton x) l] *)
@ -81,6 +85,17 @@ val fold : f:('a -> 'b -> 'a) -> init:'a -> 'b t -> 'a
val foldi : f:('a -> int -> 'b -> 'a) -> init:'a -> 'b t -> 'a val foldi : f:('a -> int -> 'b -> 'a) -> init:'a -> 'b t -> 'a
(** Fold over elements of the sequence and their index, consuming it *) (** Fold over elements of the sequence and their index, consuming it *)
val fold_map : f:('acc -> 'a -> 'acc * 'b) -> init:'acc -> 'a t -> 'b t
(** [fold_map f acc l] is like {!map}, but it carries some state as in
{!fold}. The state is not returned, it is just used to thread some
information to the map function.
@since 0.9 *)
val fold_filter_map : f:('acc -> 'a -> 'acc * 'b option) -> init:'acc -> 'a t -> 'b t
(** [fold_filter_map f acc l] is a {!fold_map}-like function, but the
function can choose to skip an element by retuning [None].
@since 0.9 *)
val map : f:('a -> 'b) -> 'a t -> 'b t val map : f:('a -> 'b) -> 'a t -> 'b t
(** Map objects of the sequence into other elements, lazily *) (** Map objects of the sequence into other elements, lazily *)
@ -105,6 +120,20 @@ val mem : ?eq:('a -> 'a -> bool) -> x:'a -> 'a t -> bool
val find : f:('a -> 'b option) -> 'a t -> 'b option val find : f:('a -> 'b option) -> 'a t -> 'b option
(** Find the first element on which the function doesn't return [None] *) (** Find the first element on which the function doesn't return [None] *)
val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
(** Indexed version of {!find}
@since 0.9 *)
val find_pred : f:('a -> bool) -> 'a t -> 'a option
(** [find_pred p l] finds the first element of [l] that satisfies [p],
or returns [None] if no element satisfies [p]
@since 0.9 *)
val find_pred_exn : f:('a -> bool) -> 'a t -> 'a
(** Unsafe version of {!find_pred}
@raise Not_found if no such element is found
@since 0.9 *)
val length : 'a t -> int val length : 'a t -> int
(** How long is the sequence? Forces the sequence. *) (** How long is the sequence? Forces the sequence. *)
@ -126,14 +155,12 @@ val concat : 'a t t -> 'a t
val flatten : 'a t t -> 'a t val flatten : 'a t t -> 'a t
(** Alias for {!concat} *) (** Alias for {!concat} *)
val flatMap : f:('a -> 'b t) -> 'a t -> 'b t
(** @deprecated use {!flat_map} *)
val flat_map : f:('a -> 'b t) -> 'a t -> 'b t val flat_map : f:('a -> 'b t) -> 'a t -> 'b t
(** Alias to {!flatMap} with a more explicit name *) (** Alias to {!flatMap} with a more explicit name *)
val fmap : f:('a -> 'b option) -> 'a t -> 'b t val flat_map_l : f:('a -> 'b list) -> 'a t -> 'b t
(** @deprecated use {!filter_map} *) (** Convenience function combining {!flat_map} and {!of_list}
@since 0.9 *)
val filter_map : f:('a -> 'b option) -> 'a t -> 'b t val filter_map : f:('a -> 'b option) -> 'a t -> 'b t
(** Alias to {!fmap} with a more explicit name *) (** Alias to {!fmap} with a more explicit name *)
@ -170,8 +197,20 @@ val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
(** Sort the sequence and remove duplicates. Eager, same as [sort] *) (** Sort the sequence and remove duplicates. Eager, same as [sort] *)
val group : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t val sorted : ?cmp:('a -> 'a -> int) -> 'a t -> bool
(** Group equal consecutive elements. *) (** Checks whether the sequence is sorted. Eager, same as {!sort}.
@since 0.9 *)
val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t
(** Group equal consecutive elements.
Formerly synonym to [group].
@since 0.6 *)
val group_by : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) ->
'a t -> 'a list t
(** Group equal elements, disregarding their order of appearance.
The result sequence is traversable as many times as required.
@since 0.6 *)
val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t
(** Remove consecutive duplicate elements. Basically this is (** Remove consecutive duplicate elements. Basically this is
@ -183,6 +222,16 @@ val product : 'a t -> 'b t -> ('a * 'b) t
as required (several times), possibly by calling {!persistent} on it as required (several times), possibly by calling {!persistent} on it
beforehand. *) beforehand. *)
val diagonal_l : 'a list -> ('a * 'a) t
(** All pairs of distinct positions of the list. [diagonal l] will
return the sequence of all [List.nth i l, List.nth j l] if [i < j].
@since 0.9 *)
val diagonal : 'a t -> ('a * 'a) t
(** All pairs of distinct positions of the sequence.
Iterates only once on the sequence, which must be finite.
@since 0.9 *)
val product2 : 'a t -> 'b t -> ('a, 'b) t2 val product2 : 'a t -> 'b t -> ('a, 'b) t2
(** Binary version of {!product}. Same requirements. *) (** Binary version of {!product}. Same requirements. *)
@ -369,6 +418,17 @@ val int_range_dec : start:int -> stop:int -> int t
(** Iterator on decreasing integers in [stop...start] by steps -1. (** Iterator on decreasing integers in [stop...start] by steps -1.
See {!(--^)} for an infix version *) See {!(--^)} for an infix version *)
val int_range_by : step:int -> start:int -> stop:int -> int t
(** [int_range_by ~step ~start:i ~stop:j] is the range starting at [i], including [j],
where the difference between successive elements is [step].
use a negative [step] for a decreasing sequence.
@since 0.9
@raise Invalid_argument if [step=0] *)
val bools : bool t
(** Iterates on [true] and [false]
@since 0.9 *)
val of_set : (module Set.S with type elt = 'a and type t = 'b) -> 'b -> 'a t 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. *) (** Convert the given set to a sequence. The set module must be provided. *)