'General approach to modifying an array while looping through it

Is it safe in Perl6 (as opposed to perl5 or other languages) to loop through an array while modifying it? For instance, if I have an array of websites to download, and I add failed downloads to the end of the array to re-download, will perl6 behave as expected? (I have about 50k links to download and trying to test all out would be time consuming.)

If not safe, what is a general approach? I have been thinking of storing links of interrupted downloads in another array, and loop through that array after original array was done. However, this is like a fox chasing its tail because I have to store failed downloads in another array (or overwrite the original array).



Solution 1:[1]

It is definitely safe in a single-threaded environment:

my @a = ^5;
for @a { 
    @a.push: $_ + 10 if $_ < 30
}
say @a

[1 2 3 4 11 12 13 14 21 22 23 24 31 32 33 34]

In a multi-threaded environment (which is what is better be used in your task) nothing can be taken for granted. Therefore appending of a new element to the array is better be wrapped into a Lock:

my @a = ^5;
my Lock $l .= new;
for @a {
    start {
        ... # Do your work here 
        $l.protect: {
            @a.push: $_ with $site
        }
    }
}
say @a

Note that the last sample won't work as expected because all started threads must be awaited somewhere within the loop. Consider it just as a basic demo.

Yet, locking is usually be avoided whenever possible. A better solution would use Channel and react/whenever blocks.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Vadim Belman