perl6 grep как программа параллельно - PullRequest
0 голосов
/ 29 июня 2018

Я написал grep-подобную программу на perl6, и теперь я превратил ее в параллельную обработку. Но я столкнулся с некоторой проблемой: даже с одной и той же командной строкой программа иногда завершается успешно, а иногда дает сбой. Когда это удается, все выглядит нормально для меня. Когда это терпит неудачу, я не знаю почему ...

Вот сообщение об ошибке при сбое.

> grep6 perl *
An operation first awaited:
in sub MAIN at /Users/xxx/Dropbox/bin/grep6 line 28
in block <unit> at /Users/xxx/Dropbox/bin/grep6 line 30

Died with the exception:
Cannot find method 'Any' on object of type Match
  in regex  at /Users/xxx/Dropbox/bin/grep6 line 34
  in sub do_something at /Users/xxx/Dropbox/bin/grep6 line 34
  in block  at /Users/xxx/Dropbox/bin/grep6 line 24

И код:

#!/usr/bin/env perl6  

constant $color_red = "\e[31m";
constant $color_off = "\e[0m";

sub MAIN(Str $pattern, *@filenames){
    my $channel = Channel.new();
    $channel.send($_) for @filenames; # dir();
    $channel.close;
    my @workers;
    for 1..3 -> $n {
        push @workers, start {
            while (my $file = $channel.poll) {
                do_something($pattern, $file);
            }
        } 
    }
    await(@workers);
}

sub do_something(Str $pattern, Str $filename) {
    #say $filename;
    for $filename.IO.lines -> $line  {
        my Str $temp = $line;
        if $temp ~~ s:g/ (<$pattern>) /$color_red$0$color_off/ { 
            say $filename ~ ": " ~ $temp;
        }
    }
}

У меня вопрос, почему иногда он терпит неудачу?

Привет

Xin

Ответы [ 2 ]

0 голосов
/ 29 июня 2018

Эта проблема, по-видимому, аналогична известной проблеме rakudo для метода race .

Я перешел с:

if $temp ~~ s:g/ (<$pattern>) /$color_red$0$color_off/ { 

до:

if $temp ~~ s:g/ ($pattern) /$color_red$0$color_off/ { 

и проблема, казалось, ушла.

Как позже упомянул Синь Чен и также описал в том же документе, более простая интерполяция соответствует буквально, как пояснено примерами из документа. Билет исправил проблему с чем-то вроде:

my $reg = regex { <$pattern> };
'' ~~ $reg;

ведет к обновленной программе с похожим обходным путем:

#!/usr/bin/env perl6

constant $color_red = "\e[31m";
constant $color_off = "\e[0m";

sub MAIN(Str $pattern, *@filenames){
    my $channel = Channel.new();
    $channel.send($_) for @filenames; # dir();
    $channel.close;
    my @workers;    

    # match seems required for pre-compilation
    '' ~~ (my regex pat_regex { <$pattern> });

    for 1..3 -> $n {
        push @workers, start {
            while (my $file = $channel.poll) {
                do_something(&pat_regex, $file);
            }
        }
    }
    await(@workers);
}

sub do_something(Regex $pat_regex, Str $filename) {
#    say $filename;
    for $filename.IO.lines -> $line  {
        my Str $temp = $line;
        if $temp ~~ s:g/ ($pat_regex) /$color_red$0$color_off/ {
            say $filename ~ ": " ~ $temp;
        }
    }
}

Приношу свои извинения за ранее предложенное явное решение EVAL, о котором лучше всего сказать, что мое описание требовало лучшего решения.

0 голосов
/ 29 июня 2018

Похоже, вы немного поиграли с этой проблемой, создав анонимное регулярное выражение:

s:g/ (<$pattern>) /$color_red$0$color_off/

Если вместо этого вы прекомпилируете свое регулярное выражение (либо в do_something, либо в подпрограмме MAIN, то ошибки прекращаются. Вот обновленная do_something версия:

sub do_something(Str $pattern, Str $filename) {
    my $reg = regex { $pattern };
    for $filename.IO.lines -> $line  {
        my Str $temp = $line;
        if $temp ~~ s:g/ ($reg) /$color_red$0$color_off/ { 
            say $filename ~ ": " ~ $temp;
        }
    }
}
...