Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Seq is already in use/consumed (nested gather / take )

Tags:

raku

sub f()
{
    gather
    {
        take gather { take 3; take 4; take 5; }
        take gather { take 1; take 2; take 3; }
    }
}

say f.sort

blows with

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 so.raku line 1

Whereas

sub f()
{
    gather
    {
        take cache gather { take 3; take 4; take 5; }
        take cache gather { take 1; take 2; take 3; }
    }
}

say f.sort

Works as expected and produces ((1, 2 ,3), (3, 4, 5)). That's fine (thanks raiph). Now

sub MAIN( *@n )
{
    @n = @n || ( 3, 4, 5, -1, 111, 27, 28, 29, 1, 2 );

    chunks( @n, { $^left < $^right } )
        .sort({ [*] |$_ })
        .tail
        .say;
}

sub chunks( Iterable $list, &condition )
{
    my $windows = $list.rotor( 2 => -1, :partial ).iterator;
    my $done    = False;

    gather until $done
    {
        my Mu $window := $windows.pull-one;

        last if $window =:= IterationEnd;

        take cache gather
        {
            my $condition-result;

            while $window := $window // $windows.pull-one
            {
                $done = True and last if $window =:= IterationEnd;

                take $window[0];

                $condition-result = &condition( |$window )
                    if $window.elems == 2;

                $window := Any;
                last unless $condition-result;
            }
        }
    }
}

This should produce (27 28 29), but it doesn't. It produces (111). But when I replace take cache gather by take eager gather it works as expected.

my chunks function has the same structure than the simpler example above, I reckon and yet there seems to be a difference in the behaviour.

like image 742
Holli Avatar asked May 21 '20 15:05

Holli


2 Answers

Total rewrite

There are three plausible scenarios.

In all of them, take eager gather is the solution instead of take gather.

This leaves the outermost gather.

You can leave it as is. This means if you bound the result of the chunks call to a variable, and then did two iterating operations on it, you'd get the Seq is already in use/consumed error.

Or you can deal with that problem. You have two options, depending on whether you prefer the chunks operation to be eager or lazy. If you want it to be eager, then write the outer gather as eager gather. If you want it to be lazy, write it as cache gather.

like image 176
raiph Avatar answered Nov 18 '22 16:11

raiph


The problem seems to be in your take gather construct. It puts (still open) Seqs inside your big outer Seq. I "fixed" your code by substituting take gather by take my @x = gather and everything worked as you wish, I think.

like image 26
Massa Avatar answered Nov 18 '22 14:11

Massa