=begin pod :kind("Type") :subkind("role") :category("composite")

=TITLE role PositionalBindFailover

=SUBTITLE Failover for binding to a Positional

    role PositionalBindFailover { ... }

This role provides an interface by which an object can
be coerced into a L<Positional|/type/Positional> when binding to L<Positional|/type/Positional> parameters.

For example, L<Seq|/type/Seq> type is not L<Positional|/type/Positional>, but you can still write
the following, because it L<does|/routine/does> C<PositionalBindFailover> role:

    sub fifths(@a) {        # @a is constraint to Positional
        @a[4];
    }
    my $seq := gather {     # a Seq, which is not Positional
        take $_ for 1..*;
    }
    say fifths($seq);       # OUTPUT: «5␤»

The invocation of C<fifths> in the example above would ordinarily give a type
error, because C<$seq> is of type L<Seq|/type/Seq>, which doesn't do the
L<Positional|/type/Positional> interface that the C<@>-sigil implies.

But the signature binder recognizes that C<Seq> does the
C<PositionalBindFailover> role, and calls its C<cache> method to coerce it to
a L<List|/type/List>, which does the C<Positional> role.

The same happens with custom classes that do the role; they simply
need to provide an C<iterator> method that produces an L<Iterator|/type/Iterator>:

    class Foo does PositionalBindFailover {
        method iterator {
            class :: does Iterator {
                method pull-one {
                    return 42 unless $++;
                    IterationEnd
                }
            }.new
        }
    }

    sub first-five (@a) { @a[^5].say }
    first-five Foo.new; # OUTPUT: # OUTPUT: «(42 Nil Nil Nil Nil)␤»

=head1 Methods

=head2 method cache

    method cache(PositionalBindFailover:D: --> List:D)

Returns a L<List|/type/List> based on the C<iterator> method, and caches it.
Subsequent calls to C<cache> always return the same C<List> object.

=head2 method list

    method list(PositionalBindFailover:D: --> List:D)

Returns a L<List|/type/List> based on the C<iterator> method without caching it.

=head2 method iterator

    method iterator(PositionalBindFailover:D:) { ... }

This method stub ensure that a class implementing role
C<PositionalBindFailover> provides an C<iterator> method.

=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
