perl6 grep就像程序并行

Xin*_*eng 9 concurrency perl6

我在perl6中编写了一个类似grep的程序,现在我将它编入并行处理.但是我遇到了一些问题:即使使用相同的命令行,程序有时会成功,有时会失败.当它成功时,事情对我来说是正常的.当它失败时,我不知道为什么......

这是失败时的错误消息.

> 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
Run Code Online (Sandbox Code Playgroud)

代码是:

#!/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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么它有时会失败?

问候

mr_*_*ron 7

这个问题似乎与race方法的已知rakudo问题基本相同.

我转自:

if $temp ~~ s:g/ (<$pattern>) /$color_red$0$color_off/ { 
Run Code Online (Sandbox Code Playgroud)

至:

if $temp ~~ s:g/ ($pattern) /$color_red$0$color_off/ { 
Run Code Online (Sandbox Code Playgroud)

问题似乎消失了.

正如新程后面提到的并且也在同一文档中描述的那样,更简单的插值在字面上符合文档示例所阐明.发行票修复了以下问题:

my $reg = regex { <$pattern> };
'' ~~ $reg;
Run Code Online (Sandbox Code Playgroud)

导致更新的程序具有类似的解决方法:

#!/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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我对早先提出的明确EVAL解决方案表示道歉,我能说的最好的是我的描述要求更好的解决方案.


Sci*_*mon 5

关于这个问题的一些玩法似乎是你正在创建的匿名正则表达:

s:g/ (<$pattern>) /$color_red$0$color_off/
Run Code Online (Sandbox Code Playgroud)

如果你改为预编译你的正则表达式(无论是在例程中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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,它现在不会崩溃.当我说"grep6 perl*"之类的东西时,它会起作用,但如果我使用比字母数字符号更复杂的正则表达式,它将无效.例如,当我说"grep6'p.*l'*"时,我什么也得不到.在我看来,要使它工作,需要<$ pattern>就像构造一样,但是,正如我现在所知,这不是线程安全的. (2认同)