Compare commits

..

No commits in common. "main" and "v1.7" have entirely different histories.
main ... v1.7

13 changed files with 77 additions and 162 deletions

View file

@ -3,7 +3,7 @@ name: github pages
on:
push:
branches:
- main # Set a branch name to trigger deployment
- master # Set a branch name to trigger deployment
jobs:
deploy:
@ -11,10 +11,16 @@ jobs:
steps:
- uses: actions/checkout@main
- uses: ocaml/setup-ocaml@v3
- name: Cache opam
id: cache-opam
uses: actions/cache@v2
with:
ocaml-compiler: '4.14.x'
allow-prerelease-opam: true
path: ~/.opam
key: opam-ubuntu-latest-4.12.0
- uses: avsm/setup-ocaml@v1
with:
ocaml-version: '4.12.0'
- name: Pin
run: opam pin -n .

View file

@ -2,8 +2,10 @@ name: build
on:
push:
branches:
- main
- master
pull_request:
branches:
- master
jobs:
run:
name: Build
@ -16,15 +18,13 @@ jobs:
#- macos-latest
ocaml-compiler:
- 4.08.x
- 4.14.x
# TODO: - 5.1.x # https://github.com/ocaml/setup-ocaml/issues/733
- 4.12.x
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: ocaml/setup-ocaml@v3
- uses: ocaml/setup-ocaml@v2
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}
allow-prerelease-opam: true
- run: opam pin -n .
- run: opam depext -yt iter
- run: opam install -t . --deps-only

View file

@ -1,4 +1,4 @@
version = 0.26.2
version = 0.24.1
profile=conventional
margin=80
if-then-else=k-r

View file

@ -1,15 +1,4 @@
# 1.9
- Switch exceptions used for control flow from global to local
- Update Iter.ml to use mutable fields instead of refs (#44)
# 1.8
- add `Iter.map_while`
- fix bug in `map_by_2`, add tests
# 1.7
- add let operators in Infix

View file

@ -2,7 +2,6 @@
(names bench_persistent_read bench_persistent benchs)
(libraries iter benchmark)
(optional)
(flags :standard -w +a-4-42-44-48-50-58-32-60-70@8 -safe-string -color
always)
(flags :standard -w +a-4-42-44-48-50-58-32-60@8 -safe-string -color always)
(ocamlopt_flags :standard -O3 -color always -unbox-closures
-unbox-closures-factor 20))

View file

@ -1,7 +1,6 @@
(executable
(name test_sexpr)
(libraries iter)
(flags :standard -w +a-4-42-44-48-50-58-32-60-70@8 -safe-string -color
always)
(flags :standard -w +a-4-42-44-48-50-58-32-60@8 -safe-string -color always)
(ocamlopt_flags :standard -O3 -color always -unbox-closures
-unbox-closures-factor 20))

View file

@ -1,6 +1,6 @@
opam-version: "2.0"
name: "iter"
version: "1.9"
version: "1.7"
authors: ["Simon Cruanes" "Gabriel Radanne"]
maintainer: "simon.cruanes.2007@m4x.org"
license: "BSD-2-clause"

View file

@ -114,9 +114,7 @@ let map_by_2 f seq k =
let f y =
match !r with
| None -> r := Some y
| Some x ->
r := None;
k (f x y)
| Some x -> k (f x y)
in
seq f;
match !r with
@ -189,75 +187,63 @@ let keep_error seq k =
(** Mutable unrolled list to serve as intermediate storage *)
module MList = struct
type 'a node =
| Nil
| Cons of { a: 'a array; mutable n: int; mutable tl: 'a node }
type 'a node = Nil | Cons of 'a array * int ref * 'a node ref
(* build and call callback on every element *)
let of_iter_with seq k =
let start = ref Nil in
let chunk_size = ref 8 in
let acc = ref Nil in
let cur = ref Nil in
let tail = ref Nil in
let[@inline] replace_tail () =
match !acc with
| Nil -> acc := !cur
| _ ->
(match !tail with
| Nil -> ()
| Cons r -> r.tl <- !cur)
in
(* fill the list. prev: tail-reference from previous node *)
let prev, cur = ref start, ref Nil in
seq (fun x ->
k x;
(* callback *)
match !cur with
| Nil ->
let n = !chunk_size in
if n < 4096 then chunk_size := 2 * n;
cur := Cons { a = Array.make n x; n = 1; tl = Nil }
| Cons r ->
assert (r.n < Array.length r.a);
r.a.(r.n) <- x;
r.n <- succ r.n;
if r.n = Array.length r.a then (
replace_tail ();
tail := !cur;
if n < 4096 then chunk_size := 2 * !chunk_size;
cur := Cons (Array.make n x, ref 1, ref Nil)
| Cons (a, n, next) ->
assert (!n < Array.length a);
a.(!n) <- x;
incr n;
if !n = Array.length a then (
!prev := !cur;
prev := next;
cur := Nil
));
replace_tail ();
!acc
!prev := !cur;
!start
let of_iter seq = of_iter_with seq (fun _ -> ())
let rec iter f l =
match l with
| Nil -> ()
| Cons { a; n; tl } ->
for i = 0 to n - 1 do
| Cons (a, n, tl) ->
for i = 0 to !n - 1 do
f a.(i)
done;
iter f tl
iter f !tl
let iteri f l =
let rec iteri i f l =
match l with
| Nil -> ()
| Cons { a; n; tl } ->
for j = 0 to n - 1 do
| Cons (a, n, tl) ->
for j = 0 to !n - 1 do
f (i + j) a.(j)
done;
iteri (i + n) f tl
iteri (i + !n) f !tl
in
iteri 0 f l
let rec iter_rev f l =
match l with
| Nil -> ()
| Cons { a; n; tl } ->
iter_rev f tl;
for i = n - 1 downto 0 do
| Cons (a, n, tl) ->
iter_rev f !tl;
for i = !n - 1 downto 0 do
f a.(i)
done
@ -265,7 +251,7 @@ module MList = struct
let rec len acc l =
match l with
| Nil -> acc
| Cons { n; tl; _ } -> len (acc + n) tl
| Cons (_, n, tl) -> len (acc + !n) !tl
in
len 0 l
@ -273,8 +259,8 @@ module MList = struct
let rec get l i =
match l with
| Nil -> raise (Invalid_argument "MList.get")
| Cons { a; n; _ } when i < n -> a.(i)
| Cons { n; tl; _ } -> get tl (i - n)
| Cons (a, n, _) when i < !n -> a.(i)
| Cons (_, n, tl) -> get !tl (i - !n)
let to_iter l k = iter k l
@ -285,11 +271,11 @@ module MList = struct
let rec get_next _ =
match !cur with
| Nil -> None
| Cons { n; tl; _ } when !i = n ->
cur := tl;
| Cons (_, n, tl) when !i = !n ->
cur := !tl;
i := 0;
get_next arg
| Cons { a; _ } ->
| Cons (a, _, _) ->
let x = a.(!i) in
incr i;
Some x
@ -302,8 +288,8 @@ module MList = struct
let rec make (l, i) () =
match l with
| Nil -> Seq.Nil
| Cons { n; tl; _ } when i = n -> make (tl, 0) ()
| Cons { a; _ } -> Seq.Cons (a.(i), make (l, i + 1))
| Cons (_, n, tl) when i = !n -> make (!tl, 0) ()
| Cons (a, _, _) -> Seq.Cons (a.(i), make (l, i + 1))
in
make (l, 0)
end
@ -330,8 +316,9 @@ let sort ?(cmp = Stdlib.compare) seq =
let l = List.fast_sort cmp l in
fun k -> List.iter k l
exception Exit_sorted
let sorted ?(cmp = Stdlib.compare) seq =
let exception Exit_sorted in
let prev = ref None in
try
seq (fun x ->
@ -555,8 +542,9 @@ let diff (type a) ?(eq = ( = )) ?(hash = Hashtbl.hash) c1 c2 =
c2 (fun x -> Tbl.replace tbl x ());
fun yield -> c1 (fun x -> if not (Tbl.mem tbl x) then yield x)
exception Subset_exit
let subset (type a) ?(eq = ( = )) ?(hash = Hashtbl.hash) c1 c2 =
let exception Subset_exit in
let module Tbl = Hashtbl.Make (struct
type t = a
@ -628,8 +616,9 @@ let sumf seq : float =
sum := t);
!sum
exception ExitHead
let head seq =
let exception ExitHead in
let r = ref None in
try
seq (fun x ->
@ -643,8 +632,9 @@ let head_exn seq =
| None -> invalid_arg "Iter.head_exn"
| Some x -> x
exception ExitTake
let take n seq k =
let exception ExitTake in
let count = ref 0 in
try
seq (fun x ->
@ -653,8 +643,9 @@ let take n seq k =
k x)
with ExitTake -> ()
exception ExitTakeWhile
let take_while p seq k =
let exception ExitTakeWhile in
try
seq (fun x ->
if p x then
@ -663,20 +654,9 @@ let take_while p seq k =
raise_notrace ExitTakeWhile)
with ExitTakeWhile -> ()
let map_while f seq k =
let exception ExitMapWhile in
let consume x =
match f x with
| `Yield y -> k y
| `Return y ->
k y;
raise_notrace ExitMapWhile
| `Stop -> raise_notrace ExitMapWhile
in
try seq consume with ExitMapWhile -> ()
exception ExitFoldWhile
let fold_while f s seq =
let exception ExitFoldWhile in
let state = ref s in
let consume x =
let acc, cont = f !state x in
@ -715,16 +695,18 @@ let rev seq =
let l = MList.of_iter seq in
fun k -> MList.iter_rev k l
exception ExitForall
let for_all p seq =
let exception ExitForall in
try
seq (fun x -> if not (p x) then raise_notrace ExitForall);
true
with ExitForall -> false
exception ExitExists
(** Exists there some element satisfying the predicate? *)
let exists p seq =
let exception ExitExists in
try
seq (fun x -> if p x then raise_notrace ExitExists);
false
@ -732,8 +714,9 @@ let exists p seq =
let mem ?(eq = ( = )) x seq = exists (eq x) seq
exception ExitFind
let find_map f seq =
let exception ExitFind in
let r = ref None in
(try
seq (fun x ->
@ -748,7 +731,6 @@ let find_map f seq =
let find = find_map
let find_mapi f seq =
let exception ExitFind in
let i = ref 0 in
let r = ref None in
(try
@ -782,8 +764,9 @@ let[@inline] length seq =
seq (fun _ -> incr r);
!r
exception ExitIsEmpty
let is_empty seq =
let exception ExitIsEmpty in
try
seq (fun _ -> raise_notrace ExitIsEmpty);
true
@ -1031,14 +1014,9 @@ module Map = struct
let of_iter_ seq = fold (fun m (k, v) -> M.add k v m) M.empty seq
let keys m = from_iter (fun k -> M.iter (fun x _ -> k x) m)
let values m = from_iter (fun k -> M.iter (fun _ y -> k y) m)
[@@@ocaml.warning "-32"]
let of_list l = of_iter_ (of_list l)
let to_list x = to_list (to_iter_ x)
[@@@ocaml.warning "+32"]
include M
let to_iter = to_iter_

View file

@ -487,18 +487,6 @@ val take_while : ('a -> bool) -> 'a t -> 'a t
Will work on an infinite iterator [s] if the predicate is false for at
least one element of [s]. *)
val map_while : ('a -> [ `Yield of 'b | `Return of 'b | `Stop ]) -> 'a t -> 'b t
(** Maps over elements of the iterator, stopping early if the mapped function
returns [`Stop] or [`Return x]. At each iteration:
{ul
{- If [f] returns [`Yield y], [y] is added to the sequence and the
iteration continues.}
{- If [f] returns [`Stop], nothing is added to the sequence and the
iteration stops.}
{- If [f] returns [`Return y], [y] is added to the sequence and the
iteration stops.}}
@since 1.8 *)
val fold_while : ('a -> 'b -> 'a * [ `Stop | `Continue ]) -> 'a -> 'b t -> 'a
(** Folds over elements of the iterator, stopping early if the accumulator
returns [('a, `Stop)]

View file

@ -22,4 +22,4 @@ let mmap filename yield =
with e ->
Unix.close fd;
raise e
[@@ocaml.warning "-3"]
[@@ocaml.warning "-3"]

View file

@ -1,9 +1,10 @@
(library
(name iter)
(public_name iter)
(wrapped false)
(modules Iter IterLabels)
(flags :standard -w +a-4 -warn-error -a+8 -nolabels))
(flags :standard -w +a -warn-error -a+8 -nolabels))
(env
(_

View file

@ -1,3 +1,4 @@
(tests
(names t_iter)
(libraries iter qcheck-core qcheck-core.runner ounit2))
(names t_iter)
(libraries iter qcheck-core qcheck-core.runner ounit2))

View file

@ -237,31 +237,6 @@ let () =
OUnit.assert_equal 2 n;
()
let list_equal eq l1 l2 =
List.length l1 = List.length l2 && List.for_all2 eq l1 l2
let () =
OUnit.assert_equal ~cmp:(list_equal Int.equal)
(1 -- 10
|> map_while (fun x ->
if x = 7 then
`Return (x + 1)
else
`Yield (x - 1))
|> to_list)
[ 0; 1; 2; 3; 4; 5; 8 ]
let () =
OUnit.assert_equal ~cmp:(list_equal Int.equal)
(1 -- 10
|> map_while (fun x ->
if x = 7 then
`Stop
else
`Yield (x - 1))
|> to_list)
[ 0; 1; 2; 3; 4; 5 ]
let () = 1 -- 5 |> drop 2 |> to_list |> OUnit.assert_equal [ 3; 4; 5 ]
let () = 1 -- 5 |> rev |> to_list |> OUnit.assert_equal [ 5; 4; 3; 2; 1 ]
@ -372,24 +347,3 @@ let () =
let () =
let errcode = QCheck_base_runner.run_tests ~colors:false !qchecks in
if errcode <> 0 then exit errcode
(* map_by_2 tests *)
let test = OUnit.assert_equal ~printer:Q.Print.(list int)
let () = test [] (map_by_2 (fun a _ -> a) (of_list []) |> to_list)
(* Test empty iterator *)
let () = test [ 1 ] (map_by_2 (fun _ b -> b) (of_list [ 1 ]) |> to_list)
let () = test [ 3 ] (map_by_2 (fun _ b -> b) (1 -- 3) |> drop 1 |> to_list)
let () = test [ 9 ] (map_by_2 (fun _ b -> b) (1 -- 9) |> drop 4 |> to_list)
(* Odd number of elements should leave the last element in the iterator.
For an increasing integer range [1,2k] (fun _ b -> b) returns only
even numbers so this is sufficient to test that this element is left
in the iterator. *)
let () = test [ 1 ] (map_by_2 (fun a _ -> a) (1 -- 2) |> to_list)
let () = test [ 2 ] (map_by_2 (fun _ b -> b) (1 -- 2) |> to_list)
(* Test two elements *)
let () = test [ 1; 3; 5; 7; 9 ] (map_by_2 (fun a _ -> a) (1 -- 10) |> to_list)
let () = test [ 2; 4; 6; 8; 10 ] (map_by_2 (fun _ b -> b) (1 -- 10) |> to_list)
(* Test more than two elements *)