Skip to content

Commit

Permalink
Introducing/Using the CachedIterator role
Browse files Browse the repository at this point in the history
This is CachedIterator role is a refinement of the PredictiveIterator role.
The difference is that a CachedIterator role is supposed to supply a "cache"
method that will be called to set the cache of the Seq as soon as the iterator
is being used.

By having R:Iterator.ReifiedArrayIterator and R:Iterator.ReifiedListIterator
consume this role, makes the following code work again:

    given Seq.new((1,2,3).iterator) {
        dd .elems; dd .all; dd .all
    }
    # 3
    # all(1, 2, 3)
    # all(1, 2, 3)

which was broken by:

  9107215
  • Loading branch information
lizmat committed Jun 12, 2019
1 parent 7af0fb1 commit 94ba19f
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 3 deletions.
8 changes: 8 additions & 0 deletions src/core/Iterator.pm6
Expand Up @@ -131,4 +131,12 @@ my role PredictiveIterator does Iterator {
method bool-only(--> Bool:D) { self.count-only.Bool }
}

# The CachedIterator role is a refinement of the PredictiveIterator role for
# those cases when all values have been generated already. It prevents the
# already generated values from being cached yet again for a Sequence.
my role CachedIterator does PredictiveIterator {
# The "cache" method should return a List of the already generated values.
method cache(--> List:D) { ... }
}

# vim: ft=perl6 expandtab sw=4
10 changes: 8 additions & 2 deletions src/core/Rakudo/Iterator.pm6
Expand Up @@ -2612,7 +2612,7 @@ class Rakudo::Iterator {
# Return an iterator for an Array that has been completely reified
# already. Returns a assignable container for elements don't exist
# before the end of the reified array.
my class ReifiedArrayIterator does PredictiveIterator {
my class ReifiedArrayIterator does CachedIterator {
has $!reified;
has $!descriptor;
has int $!i;
Expand Down Expand Up @@ -2701,6 +2701,9 @@ class Rakudo::Iterator {
- nqp::islt_i($!i,nqp::elems($!reified))
)
}
method cache(--> List:D) {
nqp::p6bindattrinvres(nqp::create(List),List,'$!reified',$!reified)
}
method sink-all(--> IterationEnd) { $!i = nqp::elems($!reified) }
}
method ReifiedArray(\array, Mu \descriptor) {
Expand All @@ -2710,7 +2713,7 @@ class Rakudo::Iterator {
# Return an iterator for a List that has been completely reified
# already. Returns an nqp::null for elements that don't exist
# before the end of the reified list.
my class ReifiedListIterator does PredictiveIterator {
my class ReifiedListIterator does CachedIterator {
has $!reified;
has int $!i;

Expand Down Expand Up @@ -2791,6 +2794,9 @@ class Rakudo::Iterator {
- nqp::islt_i($!i,nqp::elems($!reified))
)
}
method cache(--> List:D) {
nqp::p6bindattrinvres(nqp::create(List),List,'$!reified',$!reified)
}
method sink-all(--> IterationEnd) { $!i = nqp::elems($!reified) }
}
method ReifiedList(\list) {
Expand Down
8 changes: 7 additions & 1 deletion src/core/Seq.pm6
Expand Up @@ -19,7 +19,13 @@ my class Seq is Cool does Iterable does Sequence {
nqp::if(
nqp::isconcrete(my \iter = $!iter),
nqp::stmts(
($!iter := Iterator),
($!iter := Iterator), # allow usage only once
nqp::if(
nqp::istype(iter,CachedIterator),
nqp::bindattr( # can set up cache now
self,::?CLASS,'$!list',nqp::decont(iter.cache)
)
),
iter
),
nqp::if(
Expand Down

0 comments on commit 94ba19f

Please sign in to comment.