Skip to content

Commit

Permalink
Implement Foo.pick(**)
Browse files Browse the repository at this point in the history
This will produce all values of Foo.pick(*), and then produce all values
of Foo.pick(*) again, and again, ad infinitum.

This removes some unnecessary protos.  And adds a Rakudo::Iterator.Reiterate
method to produce values from a Callable that produces an iterator.

The Any.pick(HyperWhatever) candidate needs to be marked as "default"
because of ambiguity with List.pick(Any).
  • Loading branch information
lizmat committed Jun 16, 2021
1 parent db074a8 commit cd4a72b
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 5 deletions.
3 changes: 3 additions & 0 deletions src/core.c/Any.pm6
Expand Up @@ -132,6 +132,9 @@ my class Any { # declared in BOOTSTRAP
proto method pick(|) is nodal {*}
multi method pick() { self.list.pick }
multi method pick($n) { self.list.pick($n) }
multi method pick(HyperWhatever) is default {
Seq.new: Rakudo::Iterator.Reiterate: { self.pick(Whatever).iterator }
}

proto method roll(|) is nodal {*}
multi method roll() { self.list.roll }
Expand Down
1 change: 0 additions & 1 deletion src/core.c/Baggy.pm6
Expand Up @@ -389,7 +389,6 @@ my role Baggy does QuantHash {
X::Immutable.new( method => 'grab', typename => self.^name ).throw;
}

proto method pick(|) {*}
multi method pick(Baggy:D:) { self.roll }
multi method pick(Baggy:D: Callable:D $calculate) {
self.pick( $calculate(self.total) )
Expand Down
1 change: 0 additions & 1 deletion src/core.c/List.pm6
Expand Up @@ -922,7 +922,6 @@ my class List does Iterable does Positional { # declared in BOOTSTRAP
)
}

proto method pick(|) is nodal {*}
multi method pick(List:D:) {
self.is-lazy
?? self.fail-iterator-cannot-be-lazy('.pick from')
Expand Down
24 changes: 24 additions & 0 deletions src/core.c/Rakudo/Iterator.pm6
Expand Up @@ -3603,6 +3603,30 @@ class Rakudo::Iterator {
ReifiedRotateIterator.new(rotate, list, descriptor)
}

# Return a lazy iterator that takes a Callable that returns an iterator,
# produces the values of that iterator until it is exhausted, then gets
# an iterator by calling the Callable again, ad infinitum.
my class Reiterate does Iterator {
has &!reiterator;
has $!iterator;

method !SET-SELF(&reiterator) {
&!reiterator := &reiterator;
$!iterator := reiterator();
self
}
method new(\reiterator) { nqp::create(self)!SET-SELF(reiterator) }
method pull-one() {
nqp::if(
nqp::eqaddr((my \pulled := $!iterator.pull-one),IterationEnd),
($!iterator := &!reiterator()).pull-one,
pulled
)
}
method is-lazy(--> True) { } # we're lazy, always
}
method Reiterate(\reiterator) { Reiterate.new(reiterator) }

# Return a lazy iterator that will repeat the values of a given
# source iterator indefinitely. Even when given a lazy iterator,
# it will cache the values seen to handle case that the iterator
Expand Down
2 changes: 0 additions & 2 deletions src/core.c/Range.pm6
Expand Up @@ -536,8 +536,6 @@ my class Range is Cool does Iterable does Positional {
!! Seq.new(Rakudo::Iterator.Empty)
}

proto method pick(|) {*}

my class PickN does Iterator {
has $!min;
has $!elems;
Expand Down
1 change: 0 additions & 1 deletion src/core.c/Setty.pm6
Expand Up @@ -165,7 +165,6 @@ my role Setty does QuantHash {
proto method grab(|) {*}
proto method grabpairs(|) {*}

proto method pick(|) {*}
multi method pick(Setty:D:) { self.roll }
multi method pick(Setty:D: Callable:D $calculate) {
self.pick( $calculate(self.elems) )
Expand Down

0 comments on commit cd4a72b

Please sign in to comment.