Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cumulative Z op throws a "The iterator of this Seq is already in use/consumed by another Seq"

Tags:

raku

This is another way of solving previous question

my @bitfields;
for ^3 -> $i {
    @bitfields[$i] = Bool.pick xx 3;
}

my @total = [\Z+] @bitfields;
say @total;

It should zip-add every row to the next one, and accumulate the value. However, this yields the error

The iterator of this Seq is already in use/consumed by another Seq
(you might solve this by adding .cache on usages of the Seq, or
by assigning the Seq into an array)
  in block <unit> at vanishing-total.p6 line 8

Any idea how this might be solved?

like image 221
jjmerelo Avatar asked Jan 31 '19 18:01

jjmerelo


1 Answers

First xx creates a Sequence

say (Bool.pick xx 3).^name; # Seq

So you probably want to turn that into an Array (or List).

for ^3 -> $i {
    @bitfields[$i] = [Bool.pick xx 3];
}

Also rather than .pick xx 3, I would use .roll(3).

for ^3 -> $i {
    @bitfields[$i] = [Bool.roll(3)];
}

The zip (Z) meta operator creates Sequences as well.

say ( [1,2] Z [3,4] ).perl;
# ((1, 3), (2, 4)).Seq

say ( [1,2] Z+ [3,4] ).perl
# (4, 6).Seq

So [\Z+] won't even work the way you want for two inputs.

say [\Z+]( [1,2], [3,4] ).perl;
# (Seq.new-consumed(), Seq.new-consumed()).Seq

say [\Z+]( 1, 2 ).perl;
# (Seq.new-consumed(), Seq.new-consumed()).Seq

It does work if you do something to cache the intermediate values.

say [\Z+]( [1,2], [3,4] ).map(*.cache).perl
# ((3,), (4, 6)).Seq

say [\Z+]( [1,2], [3,4] ).map(*.list).perl
# ((3,), (4, 6)).Seq

say [\Z+]( [1,2], [3,4] ).map(*.Array).perl
# ([3], [4, 6]).Seq

You might want to also add a list to the front, and a .skip.

my @bitfields = [
  [Bool::True,  Bool::True,  Bool::False],
  [Bool::False, Bool::False, Bool::True ],
  [Bool::False, Bool::True,  Bool::True ]
];

say [\Z+](  @bitfields  ).map(*.List)
# ((2) (1 1 1) (1 2 2))

say [\Z+](  (0,0,0), |@bitfields  ).map(*.List).skip
# ((1 1 0) (1 1 1) (1 2 2))

If you don't need the intermediate results [Z+] would work just fine.

say [Z+]( Bool.roll(3) xx 3 ) for ^5;
# (0 1 3)
# (1 2 1)
# (1 0 3)
# (0 1 2)
# (1 2 2)
like image 133
Brad Gilbert Avatar answered Oct 26 '22 20:10

Brad Gilbert