Module Persistent.Iter
The submodule Iter offers an implementation of iterators on persistent sequences.
Overview
Types
type 'a iter'a iteris the type of an iterator. If the sequence has n elements, then an iterator can be thought of as an integer index that lies in the closed interval[-1, n]. The special indices-1andndesignate the two sentinel elements, while the ordinary indices in the semi-open interval[0, n)designate the actual elements of the sequence.
Creation Operations
val create : direction -> 'a t -> 'a itercreate forward screates an iterator that points to index0. This means that the iterator points to the first element of the sequence, if the sequence is nonempty, and points to the back sentinel if the sequence is empty. Symmetrically,create backward screates an iterator that points to indexn-1, wherenis the length of the sequence. This means that the iterator points to the last element of the sequence, if the sequence is nonempty, and points to the front sentinel if the sequence is empty.Time complexity: O(1).
val reset : direction -> 'a iter -> unitreset dir itresets the iteratoritto the same initial state that is established when a new iterator is created bycreate dir (sequence it). Thus,reset forward itis equivalent toreach it 0, andreset backward itis equivalent toreach it (length it - 1).Time complexity: O(1).
Accessors
val sequence : 'a iter -> 'a tsequence itis the sequence that the iteratoritnavigates. Throughout its lifetime, an iterator remains attached to the same sequence.Time complexity: O(1).
val length : 'a iter -> Sek__.PublicSignature.lengthlength itis the length of the sequence that the iteratoritnavigates. It is a short-hand forlength (sequence it).Time complexity: O(1).
val index : 'a iter -> Sek__.PublicSignature.indexindex itis the index that the iteratoritcurrently points to. It lies in the closed interval[-1, length it]. The special indices-1andndesignate the two sentinel elements, while the ordinary indices in the semi-open interval[0, n)designate the actual elements of the sequence.Time complexity: O(1).
val finished : 'a iter -> boolfinished ittests whether the iteratoritcurrently points to the front or back sentinel. Thus,finished itis equivalent toindex it = -1 || index it = length it. Its use is recommended, as it is both more readable and more efficient than testing a condition based onindex it. The conditionnot (finished it)corresponds toit.hasNext()in Java's iterator API.Time complexity: O(1).
Read Operations
val get : 'a iter -> 'aIf
finished itisfalse, thenget itreads and returns the element that the iteratoritcurrently points to, that is, the element at indexindex it. In that case,get itis equivalent to accessing the sequence viaget (sequence it) (index it), yet is much cheaper. Iffinished itistrue, which means that the iterator points to a sentinel, thenget itraises the exceptionEnd.Time complexity: O(1).
val get_opt : 'a iter -> 'a optionget_opt itis analogous toget it, but returns an option instead of possibly raising the exceptionEnd. It is equivalent toif finished it then None else Some (get it).Time complexity: O(1).
val get_segment : direction -> 'a iter -> 'a Sek__.PublicSignature.segmentIf
finished itisfalse, thenget_segment dir itreturns a nonempty array segment, which contains a range of sequence elements. An array segment is a triple(a, j, k), whereais an array,jis the start index of the segment in the arraya, andkis the length of the segment.kmust be positive. The segment covers the array indices in the semi-open interval[j, j + k). You are allowed to read this array segment. You are not allowed to modify the arrayain any way.- If
dirisforward, then the array elementa.(j)is the current element, that is, the element that would be returned byget it. It is the first element of the segment. The last element of the segment isa.(j + k - 1). A loop of the formfor j = j to j + k - 1can be used to enumerate these elements in the forward direction.
- If
dirisbackward, then the array elementa.(j + k - 1)is the current element, that is, the element that would be returned byget it. It is the first element of the segment. The last element of the segment isa.(j). A loop of the formfor j = j + k - 1 downto jcan be used to enumerate these elements in the backward direction.
If
finished itistrue, which means that the iterator points to a sentinel, thenget_segment dir itraises the exceptionEnd.Time complexity: O(1).
- If
val get_segment_opt : direction -> 'a iter -> 'a Sek__.PublicSignature.segment optionget_segment_opt dir itis analogous toget_segment dir it, but returns an option instead of possibly raising the exceptionEnd. It is equivalent toif finished it then None else Some (get_segment dir it).Time complexity: O(1).
Move Operations
val move : direction -> 'a iter -> unitmove dir itmoves the iteratoritby one element in the directiondir. An attempt to move the iterator forward when it already points to the back sentinel, or to move it backward when it already points to the front sentinel, is forbidden: in such a situation,movemust not be called. In other words, the new indexindex it + sign dirmust lie in the closed interval[-1, length it].Time complexity: O(log n) in the worst case. However, the amortized time complexity of
moveis only O(1), in the following sense: the cost of iterating over a sequence using n successivemoveoperations is O(n).
val jump : direction -> 'a iter -> Sek__.PublicSignature.length -> unitjump dir it kmoves the iteratoritbykelements in the directiondir. The value ofkmay be positive, null, or negative. The new indexindex it + sign dir * kmust lie in the closed interval[-1, length it]. Whenkis positive,jump dir it kis equivalent to a series ofkcalls tomove dir it. Whenkis negative,jump dir it kis equivalent to a series ofkcalls tomove (opposite dir) it. The operationjump dir it 0has no effect.Time complexity: O(log n). In the particular where
abs k = 1,jumpis optimized usingmove.
val reach : 'a iter -> Sek__.PublicSignature.index -> unitreach it imoves the iteratoritso as to point to the element at indexi. Thus, after this operation,index itisi. The indeximust lie in the closed interval[-1, length it].Time complexity: O(log n). In the particular case where
i = -1ori = length it,reachis optimized and its complexity is O(1). In the particular case where one moves to the next or previous item,reachis optimized usingmove.
Read-and-Move Operations
val get_and_move : direction -> 'a iter -> 'aget_and_movecombinesgetandmove.get_and_move dir itis equivalent tolet x = get it in move dir it; x. Therefore, it raises the exceptionEndif (before the move) the iterator points to a sentinel. It corresponds toit.next()in Java's iterator API.Time complexity: same as
move.
val get_and_move_opt : direction -> 'a iter -> 'a optionget_and_move_opt dir itis analogous toget_and_move dir it, but returns an option instead of possibly raising the exceptionEnd. It is equivalent toif finished it then None else Some (get_and_move it).Time complexity: same as
move.
val get_segment_and_jump : direction -> 'a iter -> 'a Sek__.PublicSignature.segmentget_segment_and_jumpcombinesget_segmentand ajumpof the length of the segment.get_segment_and_jump dir itis equivalent tolet (_, _, k) as seg = get_segment dir it in jump dir it k; seg. Therefore, it raises the exceptionEndif (before the move) the iterator points to a sentinel.Time complexity: same as
jump. Furthermore, the total cost of iterating over a sequence of n elements usingget_segment_and_jumpis O(n/K).
val get_segment_and_jump_opt : direction -> 'a iter -> 'a Sek__.PublicSignature.segment optionget_segment_and_jump_opt dir itis analogous toget_segment_and_jump dir it, but returns an option instead of possibly raising the exceptionEnd. It is equivalent toif finished it then None else Some (get_segment_and_jump dir it).Time complexity: same as
get_segment_and_jump.
Miscellaneous Operations
val check : 'a iter -> unitIn a release build,
check itdoes nothing. In a development build, it checks that the iterator's internal invariant is satisfied.
val format : Stdlib.Format.formatter -> int iter -> unitformatis a printer for iterators over sequences of integers. It can be installed in the OCaml toplevel loop by#install_printer format. It is intended to be used only while debugging the library.