Iterator functions are typically not called as a class method, even though they are essentially constructors. For example,
use Iterator::Flex -all;
my $iter = imap { CODE } [0..10];
creates an iteration object. What is that object's class? There's a
default base Iterator class (in this case Iterator::Flex::Iterator
,
but if the caller wants to use a specialized subclass, there's no
obvious way of instructing imap
to use it. Adding extra arguments
to imap
destroys the fluid interface. Adding a companion subroutine, e.g.
imap_with_class
, forces the caller to be explicit with every call, and
requires the module to double the size of the interface.
An alternative is to indicate on a global or per-package basis which
class to use when importing Iterator::Flex
:
``` use Iterator::Flex { default_class => 'My::Iterator::One'}, '-all'; ref( imap { CODE } [0..10]; ) == 'My::Iterator::One';
package Foo{ use Iterator::Flex { class => 'My::Iterator::Two'}, '-all';
ref( imap { CODE } [0..10]; ) == 'My::Iterator::Two'; }
package Bar { use Iterator::Flex -all;
ref( imap { CODE } [0..10]; ) == 'My::Iterator::One'; }
```
Iterator::Flex
would keep track of a package's requested class via a private hash, and
the iterator subroutines would call Iterator::Flex::_instance_class
to determine which class to use:
``` sub imap {
my $class = Iterator::Flex::_instance_class( caller );
[...]
} ```