/
Iter.mli
857 lines (654 loc) · 28.6 KB
/
Iter.mli
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
(** Simple and Efficient Iterators.
The iterators are designed to allow easy transfer (mappings) between data
structures, without defining [n^2] conversions between the [n] types. The
implementation relies on the assumption that an iterator can be iterated
on as many times as needed; this choice allows for high performance
of many combinators. However, for transient iterators, the {!persistent}
function is provided, storing elements of a transient iterator
in memory; the iterator can then be used several times (See further).
Note that some combinators also return iterators (e.g. {!group}). The
transformation is computed on the fly every time one iterates over
the resulting iterator. If a transformation performs heavy computation,
{!persistent} can also be used as intermediate storage.
Most functions are {b lazy}, i.e. they do not actually use their arguments
until their result is iterated on. For instance, if one calls {!map}
on an iterator, one gets a new iterator, but nothing else happens until
this new iterator is used (by folding or iterating on it).
If an iterator is built from an iteration function that is {b repeatable}
(i.e. calling it several times always iterates on the same set of
elements, for instance List.iter or Map.iter), then
the resulting {!t} object is also repeatable. For {b one-time iter functions}
such as iteration on a file descriptor or a {!Seq},
the {!persistent} function can be used to iterate and store elements in
a memory structure; the result is an iterator that iterates on the elements
of this memory structure, cheaply and repeatably.
*)
type +'a t = ('a -> unit) -> unit
(** An iterator of values of type ['a]. If you give it a function ['a -> unit]
it will be applied to every element of the iterator successively. *)
type +'a iter = 'a t
type 'a equal = 'a -> 'a -> bool
type 'a hash = 'a -> int
(** {1 Creation} *)
val from_iter : (('a -> unit) -> unit) -> 'a t
(** Build an iterator from a iter function *)
val from_labelled_iter : (f:('a -> unit) -> unit) -> 'a t
(** Build an iterator from a labelled iter function
@since 1.2 *)
val from_fun : (unit -> 'a option) -> 'a t
(** Call the function repeatedly until it returns None. This
iterator is transient, use {!persistent} if needed! *)
val empty : 'a t
(** Empty iterator. It contains no element. *)
val singleton : 'a -> 'a t
(** Singleton iterator, with exactly one element. *)
val doubleton : 'a -> 'a -> 'a t
(** Iterator with exactly two elements *)
val init : (int -> 'a) -> 'a t
(** [init f] is the infinite iterator [f 0; f 1; f 2; …].
@since 0.9 *)
val cons : 'a -> 'a t -> 'a t
(** [cons x l] yields [x], then yields from [l].
Same as [append (singleton x) l].
Caution: it is advised not to build long iterators out of [cons],
because it's inefficient. Each additional [cons x i] adds one
layer of function call per item traversed in [i]. *)
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 iterator 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 iterator [x, f(x), f(f(x)), ...] *)
val forever : (unit -> 'b) -> 'b t
(** Iterator that calls the given function to produce elements.
The iterator 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 iterator. Assume the given iterator can
be traversed any amount of times (not transient). This yields an
infinite iterator, you should use something like {!take} not to loop
forever. *)
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
(** Iterator of intermediate results *)
(** {1 Consumption} *)
val iter : ('a -> unit) -> 'a t -> unit
(** Consume the iterator, passing all its arguments to the function.
Basically [iter f seq] is just [seq f]. *)
val iteri : (int -> 'a -> unit) -> 'a t -> unit
(** Iterate on elements and their index in the iterator *)
val for_each : 'a t -> ('a -> unit) -> unit
(** Consume the iterator, passing all its arguments to the function.
[for_each seq f] is the same as [iter f seq], i.e., [iter] with
arguments reversed.
@since 1.4 *)
val for_eachi : 'a t -> (int -> 'a -> unit) -> unit
(** Iterate on elements and their index in the iterator.
[for_eachi seq f] is the same as [iteri f seq], i.e., [iteri] with
arguments reversed.
@since 1.4 *)
val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
(** Fold over elements of the iterator, consuming it *)
val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a
(** Fold over elements of the iterator 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
(** Map objects of the iterator into other elements, lazily *)
val mapi : (int -> 'a -> 'b) -> 'a t -> 'b t
(** Map objects, along with their index in the iterator *)
val map_by_2 : ('a -> 'a -> 'a) -> 'a t -> 'a t
(** Map objects two by two. lazily.
The last element is kept in the iterator if the count is odd.
@since 0.7 *)
val for_all : ('a -> bool) -> 'a t -> bool
(** Do all elements satisfy the predicate? *)
val exists : ('a -> bool) -> 'a t -> bool
(** Exists there some element satisfying the predicate? *)
val mem : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> bool
(** Is the value a member of the iterator?
@param eq the equality predicate to use (default [(=)])
@since 0.5 *)
val find : ('a -> 'b option) -> 'a t -> 'b option
(** Find the first element on which the function doesn't return [None]
@since 0.5 *)
val find_map : ('a -> 'b option) -> 'a t -> 'b option
(** Alias to {!find}
@since 0.10 *)
val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option
(** Indexed version of {!find}
@since 0.9 *)
val find_mapi : (int -> 'a -> 'b option) -> 'a t -> 'b option
(** Alias to {!findi}
@since 0.10 *)
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
(** How long is the iterator? Forces the iterator. *)
val is_empty : 'a t -> bool
(** Is the iterator empty? Forces the iterator. *)
(** {1 Transformation} *)
val filter : ('a -> bool) -> 'a t -> 'a t
(** Filter on elements of the iterator *)
val append : 'a t -> 'a t -> 'a t
(** Append two iterators. Iterating on the result is like iterating
on the first, then on the second. *)
val append_l : 'a t list -> 'a t
(** Append iterators. Iterating on the result is like iterating
on the each iterator of the list in order.
@since 0.11 *)
val concat : 'a t t -> 'a t
(** Concatenate an iterator of iterators into one iterator. *)
val flatten : 'a t t -> 'a t
(** Alias for {!concat} *)
val flat_map : ('a -> 'b t) -> 'a t -> 'b t
(** Monadic bind. Intuitively, it applies the function to every
element of the initial iterator, and calls {!concat}.
Formerly [flatMap]
@since 0.5 *)
val flat_map_l : ('a -> 'b list) -> 'a t -> 'b t
(** Convenience function combining {!flat_map} and {!of_list}
@since 0.9 *)
val seq_list : 'a t list -> 'a list t
(** [seq_list l] returns all the ways to pick one element in each sub-iterator
in [l]. Assumes the sub-iterators can be iterated on several times.
@since 0.11 *)
val seq_list_map : ('a -> 'b t) -> 'a list -> 'b list t
(** [seq_list_map f l] maps [f] over every element of [l],
then calls {!seq_list}
@since 0.11 *)
val filter_map : ('a -> 'b option) -> 'a t -> 'b t
(** Map and only keep non-[None] elements
Formerly [fmap]
@since 0.5 *)
val filter_mapi : (int -> 'a -> 'b option) -> 'a t -> 'b t
(** Map with indices, and only keep non-[None] elements
@since 0.11 *)
val filter_count : ('a -> bool) -> 'a t -> int
(** Count how many elements satisfy the given predicate
@since 1.0 *)
val intersperse : 'a -> 'a t -> 'a t
(** Insert the single element between every element of the iterator *)
val keep_some : 'a option t -> 'a t
(** [filter_some l] retains only elements of the form [Some x].
Same as [filter_map (fun x->x)]
@since 1.0 *)
val keep_ok : ('a, _) Result.result t -> 'a t
(** [keep_ok l] retains only elements of the form [Ok x].
@since 1.0 *)
val keep_error : (_, 'e) Result.result t -> 'e t
(** [keep_error l] retains only elements of the form [Error x].
@since 1.0 *)
(** {1 Caching} *)
val persistent : 'a t -> 'a t
(** Iterate on the iterator, storing elements in an efficient internal structure..
The resulting iterator can be iterated on as many times as needed.
{b Note}: calling persistent on an already persistent iterator
will still make a new copy of the iterator! *)
val persistent_lazy : 'a t -> 'a t
(** Lazy version of {!persistent}. When calling [persistent_lazy s],
a new iterator [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. *)
(** {1 Misc} *)
val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
(** Sort the iterator. Eager, O(n) ram and O(n ln(n)) time.
It iterates on elements of the argument iterator immediately,
before it sorts them. *)
val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
(** Sort the iterator and remove duplicates. Eager, same as [sort] *)
val sorted : ?cmp:('a -> 'a -> int) -> 'a t -> bool
(** Checks whether the iterator 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. Linear time.
Formerly synonym to [group].
{b note}: Order of items in each list is unspecified.
@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.
precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold.
{b note}: Order of items in each list is unspecified.
@since 0.6 *)
val count : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> 'a t -> ('a * int) t
(** Map each distinct element to its number of occurrences in the whole seq.
Similar to [group_by seq |> map (fun l->List.hd l, List.length l)]
precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold.
@since 0.10 *)
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 iterators. 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 diagonal_l : 'a list -> ('a * 'a) t
(** All pairs of distinct positions of the list. [diagonal l] will
return the iterator 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 iterator.
Iterates only once on the iterator, which must be finite.
@since 0.9 *)
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 join_by :
?eq:'key equal ->
?hash:'key hash ->
('a -> 'key) ->
('b -> 'key) ->
merge:('key -> 'a -> 'b -> 'c option) ->
'a t ->
'b t ->
'c t
(** [join key1 key2 ~merge] is a binary operation
that takes two iterators [a] and [b], projects their
elements resp. with [key1] and [key2], and combine
values [(x,y)] from [(a,b)] with the same [key]
using [merge]. If [merge] returns [None], the combination
of values is discarded.
precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold.
@since 0.10 *)
val join_all_by :
?eq:'key equal ->
?hash:'key hash ->
('a -> 'key) ->
('b -> 'key) ->
merge:('key -> 'a list -> 'b list -> 'c option) ->
'a t ->
'b t ->
'c t
(** [join_all_by key1 key2 ~merge] is a binary operation
that takes two iterators [a] and [b], projects their
elements resp. with [key1] and [key2], and, for each key [k]
occurring in at least one of them:
- compute the list [l1] of elements of [a] that map to [k]
- compute the list [l2] of elements of [b] that map to [k]
- call [merge k l1 l2]. If [merge] returns [None], the combination
of values is discarded, otherwise it returns [Some c]
and [c] is inserted in the result.
@since 0.10 *)
val group_join_by :
?eq:'a equal ->
?hash:'a hash ->
('b -> 'a) ->
'a t ->
'b t ->
('a * 'b list) t
(** [group_join_by key2] associates to every element [x] of
the first iterator, all the elements [y] of the second
iterator such that [eq x (key y)]. Elements of the first
iterators without corresponding values in the second one
are mapped to [[]]
precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold.
@since 0.10 *)
(** {2 Set-like} *)
val inter : ?eq:'a equal -> ?hash:'a hash -> 'a t -> 'a t -> 'a t
(** Intersection of two collections. Each element will occur at most once
in the result. Eager.
precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold.
@since 0.10 *)
(*$=
[2;4;5;6] (inter (1--6) (cons 2 (4--10)) |> sort |> to_list)
[] (inter (0--5) (6--10) |> to_list)
*)
val union : ?eq:'a equal -> ?hash:'a hash -> 'a t -> 'a t -> 'a t
(** Union of two collections. Each element will occur at most once
in the result. Eager.
precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold.
@since 0.10 *)
(*$=
[2;4;5;6] (union (4--6) (cons 2 (4--5)) |> sort |> to_list)
*)
val diff : ?eq:'a equal -> ?hash:'a hash -> 'a t -> 'a t -> 'a t
(** Set difference. Eager.
@since 0.10 *)
(*$=
[1;2;8;9;10] (diff (1--10) (3--7) |> to_list)
*)
val subset : ?eq:'a equal -> ?hash:'a hash -> 'a t -> 'a t -> bool
(** [subset a b] returns [true] if all elements of [a] belong to [b]. Eager.
precondition: for any [x] and [y], if [eq x y] then [hash x=hash y] must hold.
@since 0.10 *)
(*$T
subset (2 -- 4) (1 -- 4)
not (subset (1 -- 4) (2 -- 10))
*)
(** {2 Arithmetic} *)
val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
(** Max element of the iterator, using the given comparison function.
@return None if the iterator is empty, Some [m] where [m] is the maximal
element otherwise *)
val max_exn : ?lt:('a -> 'a -> bool) -> 'a t -> 'a
(** Unsafe version of {!max}
@raise Not_found if the iterator is empty
@since 0.10 *)
val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option
(** Min element of the iterator, using the given comparison function.
see {!max} for more details. *)
val min_exn : ?lt:('a -> 'a -> bool) -> 'a t -> 'a
(** Unsafe version of {!min}
@raise Not_found if the iterator is empty
@since 0.10 *)
val sum : int t -> int
(** Sum of elements
@since 0.11 *)
val sumf : float t -> float
(** Sum of elements, using Kahan summation
@since 0.11 *)
(** {2 List-like} *)
val head : 'a t -> 'a option
(** First element, if any, otherwise [None]
@since 0.5.1 *)
val head_exn : 'a t -> 'a
(** First element, if any, fails
@raise Invalid_argument if the iterator is empty
@since 0.5.1 *)
val take : int -> 'a t -> 'a t
(** Take at most [n] elements from the iterator. Works on infinite
iterators. *)
val take_while : ('a -> bool) -> 'a t -> 'a t
(** Take elements while they satisfy the predicate, then stops iterating.
Will work on an infinite iterator [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 iterator, stopping early if the accumulator
returns [('a, `Stop)]
@since 0.5.5 *)
val drop : int -> 'a t -> 'a t
(** Drop the [n] first elements of the iterator. Lazy. *)
val drop_while : ('a -> bool) -> 'a t -> 'a t
(** Predicate version of {!drop} *)
val rev : 'a t -> 'a t
(** Reverse the iterator. O(n) memory and time, needs the
iterator to be finite. The result is persistent and does
not depend on the input being repeatable. *)
val zip_i : 'a t -> (int * 'a) t
(** Zip elements of the iterator with their index in the iterator.
@since 1.0 Changed type to just give an iterator of pairs *)
(** {2 Pair iterators} *)
val fold2 : ('c -> 'a -> 'b -> 'c) -> 'c -> ('a * 'b) t -> 'c
val iter2 : ('a -> 'b -> unit) -> ('a * 'b) t -> unit
val map2 : ('a -> 'b -> 'c) -> ('a * 'b) t -> 'c t
val map2_2 : ('a -> 'b -> 'c) -> ('a -> 'b -> 'd) -> ('a * 'b) t -> ('c * 'd) t
(** [map2_2 f g seq2] maps each [x, y] of seq2 into [f x y, g x y] *)
(** {1 Data structures converters} *)
val to_list : 'a t -> 'a list
(** Convert the iterator 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 iterator (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].
@since 0.5.2
*)
val pair_with_idx : 'a t -> (int * 'a) t
(** Similar to {!zip_i} but returns a normal iterator of tuples
@since 0.11 *)
val to_opt : 'a t -> 'a option
(** Alias to {!head}
@since 0.5.1 *)
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 array_slice : 'a array -> int -> int -> 'a t
(** [array_slice a i j] Iterator of elements whose indexes range
from [i] to [j] *)
val of_opt : 'a option -> 'a t
(** Iterate on 0 or 1 values.
@since 0.5.1 *)
val of_seq : 'a Seq.t -> 'a t
(** Iterator of elements of a {!Seq.t}.
@since 1.5 *)
val to_seq_persistent : 'a t -> 'a Seq.t
(** Convert to a {!Seq}. Linear in memory and time (a copy is made in memory).
This does not work on infinite iterators.
@since 1.5 *)
val to_stack : 'a Stack.t -> 'a t -> unit
(** Push elements of the iterator on the stack *)
val of_stack : 'a Stack.t -> 'a t
(** Iterator of elements of the stack (same order as [Stack.iter]) *)
val to_queue : 'a Queue.t -> 'a t -> unit
(** Push elements of the iterator into the queue *)
val of_queue : 'a Queue.t -> 'a t
(** Iterator of elements contained in the queue, FIFO order *)
val hashtbl_add : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
(** Add elements of the iterator to the hashtable, with
Hashtbl.add *)
val hashtbl_replace : ('a, 'b) Hashtbl.t -> ('a * 'b) t -> unit
(** Add elements of the iterator to the hashtable, with
Hashtbl.replace (erases conflicting bindings) *)
val to_hashtbl : ('a * 'b) t -> ('a, 'b) Hashtbl.t
(** Build a hashtable from an iterator of key/value pairs *)
val of_hashtbl : ('a, 'b) Hashtbl.t -> ('a * 'b) t
(** Iterator 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.
@since 0.5 *)
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 iterator). If you need to iterate
several times on this iterator, use {!persistent}.
@raise OneShotIterator when used more than once. *)
val to_buffer : char t -> Buffer.t -> unit
(** Copy content of the iterator 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 int_range_by : step:int -> int -> int -> int t
(** [int_range_by ~step i j] is the range starting at [i], including [j],
where the difference between successive elements is [step].
use a negative [step] for a decreasing iterator.
@raise Invalid_argument if [step=0] *)
val bools : bool t
(** Iterates on [true] and [false]
@since 0.7 *)
val of_set : (module Set.S with type elt = 'a and type t = 'b) -> 'b -> 'a t
(** Convert the given set to an iterator. 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 iterator to a set, given the proper set module *)
type 'a gen = unit -> 'a option
val of_gen : 'a gen -> 'a t
(** Traverse eagerly the generator and build an iterator from it *)
val of_gen_once : 'a gen -> 'a t
(** One shot iterator using this generator.
It must not be traversed twice.
@since 1.5 *)
val to_gen : 'a t -> 'a gen
(** Make the iterator persistent (O(n)) and then iterate on it. Eager. *)
(** {2 Sets} *)
module Set : sig
module type S = sig
include Set.S
val of_iter : elt iter -> t
val to_iter : t -> elt iter
val to_list : t -> elt list
val of_list : elt list -> t
val of_seq : elt iter -> t
(** @deprecated use {!of_iter} instead *)
val to_seq : t -> elt iter
(** @deprecated use {!to_iter} instead *)
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 Maps} *)
module Map : sig
module type S = sig
include Map.S
val to_iter : 'a t -> (key * 'a) iter
val of_iter : (key * 'a) iter -> 'a t
val keys : 'a t -> key iter
val values : 'a t -> 'a iter
val to_list : 'a t -> (key * 'a) list
val of_list : (key * 'a) list -> 'a t
val to_seq : 'a t -> (key * 'a) iter
(** @deprecated use {!to_iter} instead *)
val of_seq : (key * 'a) iter -> 'a t
(** @deprecated use {!of_iter} instead *)
end
(** Adapt a pre-existing Map module to make it iterator-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 iterator-aware functions *)
module Make (V : Map.OrderedType) : S with type key = V.t
end
(** {1 Random iterators} *)
val random_int : int -> int t
(** Infinite iterator of random integers between 0 and
the given higher bound (see Random.int) *)
val random_bool : bool t
(** Infinite iterator of random bool values *)
val random_float : float -> float t
val random_array : 'a array -> 'a t
(** Iterator of choices of an element in the array *)
val random_list : 'a list -> 'a t
(** Infinite iterator of random elements of the list. Basically the
same as {!random_array}. *)
val shuffle : 'a t -> 'a t
(** [shuffle seq] returns a perfect shuffle of [seq].
Uses O(length seq) memory and time. Eager.
@since 0.7 *)
val shuffle_buffer : int -> 'a t -> 'a t
(** [shuffle_buffer n seq] returns an iterator of element of [seq] in random
order. The shuffling is *not* uniform. Uses O(n) memory.
The first [n] elements of the iterator are consumed immediately. The
rest is consumed lazily.
@since 0.7 *)
(** {2 Sampling} *)
val sample : int -> 'a t -> 'a array
(** [sample n seq] returns k samples of [seq], with uniform probability.
It will consume the iterator and use O(n) memory.
It returns an array of size [min (length seq) n].
@since 0.7 *)
(** {1 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}
@since 0.5 *)
val ( >|= ) : 'a t -> ('a -> 'b) -> 'b t
(** Infix version of {!map}
@since 0.5 *)
val ( <*> ) : ('a -> 'b) t -> 'a t -> 'b t
(** Applicative operator (product+application)
@since 0.5 *)
val ( <+> ) : 'a t -> 'a t -> 'a t
(** Concatenation of iterators
@since 0.5 *)
end
include module type of Infix
(** {1 Pretty printing} *)
val pp_seq :
?sep:string ->
(Format.formatter -> 'a -> unit) ->
Format.formatter ->
'a t ->
unit
(** Pretty print an iterator 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 *)
(** Basic IO
Very basic interface to manipulate files as iterator of chunks/lines. The
iterators take care of opening and closing files properly; every time
one iterates over an iterator, the file is opened/closed again.
Example: copy a file ["a"] into file ["b"], removing blank lines:
{[
Iterator.(IO.lines_of "a" |> filter (fun l-> l<> "") |> IO.write_lines "b");;
]}
By chunks of [4096] bytes:
{[
Iterator.IO.(chunks_of ~size:4096 "a" |> write_to "b");;
]}
Read the lines of a file into a list:
{[
Iterator.IO.lines "a" |> Iterator.to_list
]}
@since 0.5.1 *)
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 iterator 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 iterator 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
(** @since 0.5.4 *)
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
(** @since 0.5.4 *)
end