NAME
Iterator::Flex::Manual::Overview - An Abstract overview of Iterators
VERSION
version 0.18
DESCRIPTION
Iterator life-cycle
There are four iterator states:
An iterator typically moves sequentially from initialized to iteration to exhausted.
Non-sequential transitions may occur from non-error states when
a data source is empty to begin with, in which case "next" will transition from the initialized state directly to the exhausted state.
something goes wrong, in which case the iterator will transition to the error state.
the iterator is "reset", in which case it transitions to the initialized state.
Attempts to transition from an error state to another state result in undefined behavior.
Initialized State
An iterator is in the initialized state immediately after it has been constructed, or if it has been reset.
In the initialized state,
"next" will attempt to retrieve the first element from the data stream.
If the data stream is empty, the iterator transitions to the "Exhausted State" and signals exhaustion.
If there was an error the iterator transitions to the "Error State" and signals error.
otherwise, the iterator transitions to the "Iteration State" and the element is returned.
"prev" and "current" (if they are supported) return an indeterminate value.
Iteration State
An iterator is in the iteration state if the last call to "next" successfully returned data.
In the iteration state,
"next" will attempt to retrieve the next element from the data stream.
If the data stream is empty, the iterator transitions to the "Exhausted State" and signals exhaustion.
If there was an error, the iterator transitions to the "Error State" and signals error.
otherwise, the element is returned.
"prev" returns
an indeterminate value If the previous call to "next" transitioned the iterator from the "Initialized State"
otherwise, the value returned by the penultimate successful call to "next".
"current" returns the value returned by the last successful call to "next".
Exhausted State
An iterator enters the exhausted state after a call to "next" when the iterator determines that there are no more data to retrieve.
In this state,
"prev" returns
an indeterminate value if the last "next" call transitioned the iterator from the "Initialized State";
otherwise, the value returned by the penultimate successful call to "next".
"current" returns an indeterminate value.
For example, if the data are 1, 2, 3, the following expressions, executed in order, are all true.
1 $iter->prev == ?; # indeterminate; in initialized state
2 $iter->current == ?; # indeterminate; in initialized state
3
4 $iter->next == 1; # in iteration state
5 $iter->prev == ?; # indeterminate
6 $iter->current == 1;
7
8 $iter->next == 2;
9 $iter->prev == 1; # from line 4
10 $iter->current == 2;
11
12 $iter->next == 3;
13 $iter->prev == 2;
14 $iter->current == 3;
15
16 $iter->next; # signals exhaustion;
17
18 $iter->is_exhausted == 1;
19
20 $iter->prev == 3;
21 $iter->current == ?; # indeterminate
22 $iter->next; # still signals exhaustion;
Error State
An iterator transitions to the error state when the iterator has determined that something went wrong.
Signaling State Transitions
The iterator signals transitions to the exhausted and error states.
Transitions to the Exhausted State
Signaling exhaustion (via the signal_exhaustion
method) results in one of following actions:
throwing an exception of type
Iterator::Flex::Failure::Exhausted
; orreturning a sentinel value
The choice is made by the user of the iterator; iterators use a generic signaling mechanism.
Transitions to the Error State
Signaling error (via the signal_error
method) results in one of following actions:
Throwing an exception of type
Iterator::Flex::Failure::Error
.
Capabilities
Iterators are capable of performing at least one task, namely retrieving the next datum in the data stream, but may be capable of others as well. These capabilities are invoked as methods with the name of the capability, e.g. $iter->next
, $iter->prev
, etc.
Required Capabilities
next
# these are equivalent
$value = $iter->next;
$value = $iter->();
This provides the ability to return the next element from the iterator. During the first call to "next" the iterator transitions from the initialized state to another (iteration, exhausted or error).
If it has made it to the iteration state, it returns a valid value, otherwise, it signals either exhaustion or error.
Invoking next will either result in a valid value, or, if the iterator is exhausted, an indication of exhaustion, which may either be
A sentinel value, indicated by the Iterator::Flex::Role::Exhaustion::Return role.
An exception, indicated by the Iterator::Flex::Role::Exhaustion::Throw role.
Optional Capabilities
prev
$value = $iter->prev;
If the iterator is in the iteration state, it returns the value returned by the penultimate "next" operation. If the last "next" operation transitioned the iterator from the initialized state, it returns an indeterminate value.
In any other state, it returns an indeterminate value.
current
$value = $iter->current;
If the iterator is in the iteration state, returns the value returned by the last "next" operation.
In any other state, it returns an indeterminate value.
rewind
$iter->rewind;
If the iterator is in the iteration state, ensures that the next "next" operation will retrieve the first element from the data stream.
Rewinding maintains the correctness of the "prev" and "current" capabilities, enabling cyclic iterators.
For example, if the data are 1, 2, 3, the following expressions, executed in order, are all true.
1 $iter->prev == ?; # indeterminate; in initialized state
2 $iter->current == ?; # indeterminate; in initialized state
3
4 $iter->next == 1; # in iteration state
5 $iter->prev == ?; # indeterminate
6 $iter->current == 1;
7
8 $iter->next == 2;
9 $iter->prev == 1; # from line 4
10 $iter->current == 2;
11
12 $iter->rewind;
13
14 $iter->prev == 1; # no change
15 $iter->current == 2; # no change
16
17 $iter->next == 1; # start all over
18 $iter->current == 1;
19 $iter->prev == 2; # from line 8
20
21 $iter->next == 2;
22 $iter->current == 2;
23 $iter->prev == 1; # from line 17
reset
$iter->reset;
Transitions the iterator to the initialized state.
For example, if the data are 1, 2, 3, the following expressions, executed in order, are all true.
1 $iter->prev == ?; # indeterminate; in initialized state
2 $iter->current == ?; # indeterminate; in initialized state
3
4 $iter->next == 1; # in iteration state
5 $iter->prev == ?; # indeterminate
6 $iter->current == 1;
7
8 $iter->next == 2;
9 $iter->prev == 1; # from line 4
10 $iter->current == 2;
11
12 $iter->reset;
14
15 $iter->prev == ?; # indeterminate; in initialized state
16 $iter->current == ?; # indeterminate; in initialized state
17
18 $iter->next == 1; # in iteration state
19 $iter->prev == ?; # indeterminate
20 $iter->current == 1;
21
22 $iter->next == 2;
23 $iter->prev == 1; # from line 18
24 $iter->current == 2;
25
freeze
$state = $iter->freeze;
$iter = ithaw( $state );
freeze
serializes the state of the iterator and the data stream so that the state can be saved and later restored. This puts significant constraints on the nature of the data source.
ithaw
is a subroutine (not a method) which is the opposite of "freeze". Given a serialized iterator, it reconstitute it so that it behaves exactly as it would before it was frozen. Under the hood it calls the thaw
method.
Generator Parameters
Parameters are passed to iterator and attribute generators, either through the convenience functions in Iterator::Flex::Common, the constructors in Iterator::Flex::Factory or the constructors in bespoke iterator classes which subclass Iterator::Flex::Base.
Classes of Parameters
There are several classes of parameters used by iterators and adapters:
Model parameters are specific to a type of iterator. For example, the cache iterator has a model parameter for the cache capacity.
Interface parameters provide implementations of the capabilities that the iterator provides.
Exhaustion parameters define how the iterator signals exhaustion.
Error parameters define how the iterator signals error.
Exhaustion, Error, and Interface parameters are also called General Parameters.
Interface Parameters
_self
-
A reference to a lexical variable which will be set by the iterator generator to a reference to the iterator object. This is used only if the iterator class consumes the Iterator::Flex::Role::Next::ClosedSelf role.
_name
-
The name of the iterator to be used in error messages. If not specified, it is set to the iterator class.
state
-
A reference to a lexical variable which will reflect whether the state is one of exhaustion, error, or something else. This is used if the iterator class consumes the Iterator::Flex::Role::State::Closure role. (The alternative is for the state to be stored in the iterator registry by consuming the Iterator::Flex::Role::State::Registry role).
Using this functionality the state stored in the lexical variable can be accessed directly from iterator closures and compared to one of the constants
IterState_EXHAUSTED
orIterState_ERROR
(see "Iterator State Constants" in Iterator::Flex::Utils).The state is also queryable via the is_exhausted and is_error iterator object methods.
class
-
The class which will consume iterator roles and from which the object will be instantiated. This option is only used by Iterator::Flex::Factory generators. It defaults to Iterator::Flex::Base.
next
-
A code reference which returns the next element in the data source. This will be made available as the object method
next
, but may also be invoked directly as a subroutine (e.g.$next->()
).Access to the iterator object can be obtained by either:
specifying the "_self" parameter and applying the Iterator::Flex::Role::Next::ClosedSelf role to the class.
applying the Iterator::Flex::Role::Wrap::Self role. The results in the creation of a wrapper ensuring that the code reference is always invoked as an object method.
prev
-
A code reference which returns the value retrieved by the penultimate call to "next". This will be made available as the object method
prev
.This is used only if the iterator class consumes the Iterator::Flex::Role::Prev::Closure role.
Classes constructed via the Iterator::Flex::Factory constructors will automatically be composed with the Iterator::Flex::Role::Prev::Method if the "prev" parameter is not specified and the class specified by the "class" parameter provides a
prev
object method.Bespoke classes should apply the Iterator::Flex::Role::Prev::Method role using the "_add_roles" in Iterator::Flex::Base class method.
current
-
A code reference which returns the value retrieved by the last call to "next". This will be made available as the object method
current
.This is used only if the iterator class consumes the Iterator::Flex::Role::Current::Closure role.
Classes constructed via the Iterator::Flex::Factory constructors will automatically be composed with the Iterator::Flex::Role::Current::Method if the "prev" parameter is not specified and the class specified by the "class" parameter provides a
prev
object method.Bespoke classes should apply the Iterator::Flex::Role::Current::Method role using the "_add_roles" in Iterator::Flex::Base class method.
reset
-
A code reference which will restore the iterator to the initialized state.
This is used only if the iterator class consumes the Iterator::Flex::Role::Reset::Closure role.
Classes constructed via the Iterator::Flex::Factory constructors will automatically be composed with the Iterator::Flex::Role::Reset::Method if the "prev" parameter is not specified and the class specified by the "class" parameter provides a
prev
object method.Bespoke classes should apply the Iterator::Flex::Role::Reset::Method role using the "_add_roles" in Iterator::Flex::Base class method.
The state variable (accessible via the is_exhausted and is_error iterator object methods) will automatically be reset.
If the iterator is an adapter depending upon other iterators, they will automatically be reset.
rewind
-
A code reference which will ensure that the next call to "next" returns the first element in the data stream.
This is used only if the iterator class consumes the Iterator::Flex::Role::Rewind::Closure role.
Classes constructed via the Iterator::Flex::Factory constructors will automatically be composed with the Iterator::Flex::Role::Rewind::Method if the "prev" parameter is not specified and the class specified by the "class" parameter provides a
prev
object method.Bespoke classes should apply the Iterator::Flex::Role::Rewind::Method role using the "_add_roles" in Iterator::Flex::Base class method.
If the iterator is an adapter depending upon other iterators, they will automatically be rewound.
freeze
-
A code reference which returns a serialized version of the iterator. See Iterator::Flex::Manual::Serialization and "Serialization" in Iterator::Flex::Manual::Caveats.
methods
-
A hash whose keys are method names and whose values are coderefs. These will be added as methods to the iterator class. Useful for making a set of closures available as methods.
_depends
-
A list of iterator objects that the adapter depends upon. Used by iterator adapters. Automatically added by Iterator::Flex::Factory constructors. Bespoke classes must provide this explicitly.
Exhaustion
There are two parameters that specify how exhaustion is signalled:
input_exhaustion
-
This applies only to iterator adapters, and indicates how the consumed iterator signals exhaustion. It can take the following values:
throw
-
The consumed iterator throws an indeterminate exception on exhaustion.
[ throw => $class ]
-
The consumed iterator throws an exception upon exhaustion in the given class on exhaustion.
[ throw => \@classes ]
-
The consumed iterator throws an exception upon exhaustion in one of the given classes on exhaustion.
[ throw => $regexp ]
-
The consumed iterator throws an exception upon exhaustion which when stringified matches the passed regular expression.
[ throw => $coderef ]
-
The consumed iterator throws an exception;
$coderef->( $e )
returns true if the exception indicates exhaustion. return
-
The consumed iterator returns a sentinel value of
undef
on exhaustion. [ return => $value ]
-
The consumed iterator returns a sentinel value of
$value
on exhaustion.
exhaustion
-
This applies to both iterators and adapters, and indicates how they signal exhaustion. It can take the following values:
[ throw => 'passthrough' ]
-
Only for adapters where the consumed iterator will throw on exhaustion; this lets that exception propagate.
throw
-
Throw an exception of Iterator::Flex::Failure::Exhaustion.
[ throw => $coderef ]
-
Invoke
$coderef
. If it does not throw, an exception of Iterator::Flex::Failure::Exhaustion. will be thrown. return
-
For both iterators and adapters, indicates that a sentinel value of
undef
will be returned. [ return => $value ]
-
For both iterators and adapters, indicates that the specified sentinel value will be returned.
Error
error
-
This applies to both iterators and adapters, and indicates how they signal error. It may have one of the following values:
throw
-
Throw an exception of Iterator::Flex::Failure::Error.
[ throw => $coderef ]
-
Invoke
$coderef
. If it does not throw, an exception of Iterator::Flex::Failure::Error. will be thrown.
INTERNALS
SUPPORT
Bugs
Please report any bugs or feature requests to bug-iterator-flex@rt.cpan.org or through the web interface at: https://rt.cpan.org/Public/Dist/Display.html?Name=Iterator-Flex
Source
Source is available at
https://gitlab.com/djerius/iterator-flex
and may be cloned from
https://gitlab.com/djerius/iterator-flex.git
SEE ALSO
Please see those modules/websites for more information related to this module.
AUTHOR
Diab Jerius <djerius@cpan.org>
COPYRIGHT AND LICENSE
This software is Copyright (c) 2018 by Smithsonian Astrophysical Observatory.
This is free software, licensed under:
The GNU General Public License, Version 3, June 2007