In role Iterator§
See primary documentation in context for method pull-one
method pull-one(Iterator:D: --> Mu)
This method stub ensures that classes implementing the Iterator
role provide a method named pull-one
.
The pull-one
method is supposed to produce and return the next value if possible, or return the sentinel value IterationEnd
if no more values could be produced.
my $i = (1 .. 3).iterator; say $i.pull-one; # OUTPUT: «1» say $i.pull-one; # OUTPUT: «2» say $i.pull-one; # OUTPUT: «3» say $i.pull-one.raku; # OUTPUT: «IterationEnd»
As a more illustrative example of its use, here is a count down iterator along with a simplistic subroutine re-implementation of the for
loop.
# works the same as (10 ... 1, 'lift off') class CountDown does Iterator { has Int:D $!current = 10; method pull-one ( --> Mu ) { my $result = $!current--; if $result == 0 { return 'lift off' } if $result == -1 { return IterationEnd } # calling .pull-one again after it returns IterationEnd is undefined if $result <= -2 { # so for fun we will give them nonsense data return (1..10).pick; } return $result; } } sub for( Iterable:D $sequence, &do --> Nil ) { my Iterator:D $iterator = $sequence.iterator; loop { # must bind the result so that =:= works my Mu $pulled := $iterator.pull-one; # always check the result and make sure that .pull-one # is not called again after it returns IterationEnd if $pulled =:= IterationEnd { last } do( $pulled ); } } for( Seq.new(CountDown.new), &say ); # OUTPUT: «10987654321lift off»
It would be more idiomatic to use while
or until
, and a sigilless variable.
until IterationEnd =:= (my \pulled = $iterator.pull-one) { do( pulled ); }