=begin pod

=TITLE role Iterable

=SUBTITLE Interface for container objects that can be iterated over

    role Iterable { }

C<Iterable> serves as an API for objects that can be iterated with the
C<for> construct and related iteration constructs, like hyper operators.

C<Iterable> objects nested in other C<Iterable> objects (but not within scalar
containers) flatten in certain contexts, for example when passed to a slurpy
parameter (C<*@a>), or on explicit calls to C<flat>.

Its important aspect is a method stub for C<iterator>.

    role DNA does Iterable {
        method iterator(){ self.comb.iterator }
    };

    my @a does DNA = 'GAATCC';
    .say for @a; # OUTPUT«G␤G␤A␤T␤C␤C␤»

=head1 Methods

=head2 method iterator

Defined as:

    method iterator() returns Iterator:D

Method stub that ensures all classes doing the C<Iterable> role have a method
C<iterator>.

It is supposed to return an L<Iterator|/type/Iterator>.

    say (1..10).iterator;

=head2 method flat

Defined as:

    method flat() returns Iterable

Returns another L<Iterable> that flattens out all iterables that the first one
returns.

For example

    say (<a b>, 'c').elems;         # 2
    say (<a b>, 'c').flat.elems;    # 3

because C<< <a b> >> is a L<List|/type/List> and thus iterable, so
C<< (<a b>, 'c').flat >> returns C<('a', 'b', 'c')>, which has three elems.

Note that the flattening is recursive, so C<((("a", "b"), "c"), "d").flat>
returns C<("a", "b", "c", "d")>, but it does not flatten itemized sublists:

    say ($('a', 'b'), 'c').perl;    # ($("a", "b"), "c")

=head2 method lazy

Defined as:

    method lazy() returns Iterable

Returns a lazy iterable wrapping the invocant.

    say (1 ... 1000).is-lazy;      # False
    say (1 ... 1000).lazy.is-lazy; # True

=head2 method hyper

Defined as:

    method hyper(Int(Cool) :$batch = 64, Int(Cool) :$degree = 4) returns Iterable

Returns another Iterable that is potentially iterated in parallel, with a
given batch size and degree of parallelism.

The order of elements is preserved.

    say ([1..100].hyper.map({ $_ +1 }).list);

=head2 method race

Defined as:

    method race(Int(Cool) :$batch = 64, Int(Cool) :$degree = 4) returns Iterable

Returns another Iterable that is potentially iterated in parallel, with a
given batch size and degree of parallelism (number of parallel workers).

Unlike C<hyper>, C<race> does not preserve the order of elements.

    say ([1..100].race.map({ $_ +1 }).list);

=end pod
