编译正则表达式函数时出错,为什么我会遇到这个问题?

Error while compiling regex function, why am I getting this issue?

我的 RAKU 代码:

sub comments {
    if ($DEBUG) { say "<filtering comments>\n"; }
    my @filteredtitles = ();

    # This loops through each track
    for @tracks -> $title {

        ##########################
        # LAB 1 TASK 2           #
        ##########################
        ## Add regex substitutions to remove superflous comments and all that follows them
        ## Assign to $_ with smartmatcher (~~)
        ##########################
        $_ = $title;

        if ($_) ~~ s:g:mrx/ .*<?[\(^.*]> / {

        # Repeat for the other symbols

        ########################## End Task 2

        # Add the edited $title to the new array of titles
            @filteredtitles.push: $_;
        }
    }
        # Updates @tracks
        return @filteredtitles;
}

编译结果: Error Compiling! Placeholder variable '@_' may not be used here because the surrounding block doesn't take a signature.

有什么明显的我遗漏的东西吗?感谢任何帮助。

这是我最终得到的结果:

my @tracks = <Foo Ba(r B^az>;

sub comments {

    my @filteredtitles;

    for @tracks -> $_ is copy {

        s:g / <[\(^]> //;

        @filteredtitles.push: $_;
    }

    return @filteredtitles;
}

is copy 确保由 for 循环设置的变量是可变的。

只需 s:g/...//; 即可删除不需要的字符。


没有人可以帮助您的一件事是您报告的错误。我目前认为您只是感到困惑。

下面是生成该错误的代码示例:

do { @_ }

但是您共享的代码不可能产生该错误,因为它要求您的代码中有一个 @_ 变量,但实际上没有。


对于您可能会在 Whosebug 上报告的 未来 问题,我可以提供帮助的一种方法是鼓励您阅读并应用 Minimal Reproducible Example 中的指南。


虽然您的代码没有生成您所报告的错误,但如果您了解那里的一些 other 编译时间和 运行 时间错误,它可能会对您有所帮助在您分享的代码中。

Compile-time 错误:

  • 您写了s:g:mrx。这是无效的:Adverb mrx not allowed on substitution.

  • 您漏掉了 s/// 的第三个斜线。这会导致混乱(见下文)。

有几个 run-time 错误,一旦我克服了 compile-time 错误。我只讨论一个,正则表达式:

  • .*<?[...]> 匹配 任何 sub-string 最终字符是 [...] 中列出的字符之一, 然后 捕获 除了 没有最后字符 的 sub-string。在 s:g/...// 替换的上下文中,这将去除普通字符(由 .* 捕获)但保留特殊字符。

    这没有意义。

    所以我从特殊字符模式中删除了 .*?,将其从 <?[...]> 更改为(只是试图 匹配 对角色,但 捕获 如果它成功)只是 <[...]> also 尝试 match 匹配角色,但是,如果成功,does capture 也一样)。


最后一条评论是关于你犯的一个错误,这个错误很可能让你很困惑。

简而言之,s/// 结构 必须 三个 个斜杠。

在您的问题中,您的代码格式为 s/.../(或 s:g/.../ 等),没有最后的斜线。如果您尝试编译此类代码,解析器会完全混淆,因为它会认为您只是在编写一个长替换字符串。

例如,如果您编写了以下代码:

if s/foo/ { say 'foo' }
if m/bar/ { say 'bar' }

就好像你写了:

if s/foo/ { say 'foo' }\nif m/...

这反过来意味着你会得到 compile-time 错误:

Missing block
------> if m/⏏bar/ { ... }
    expecting any of:
        block or pointy block
        ...

因为 Raku(do) 会将第二个和第三个 / 之间的部分解释为它解释为 s/.../.../ 构造的替换双引号字符串,导致它在以下情况下成为 barf它遇到了 bar.

因此,回顾一下,s/// 构造需要 三个 个斜杠,而不是 两个

(我忽略了结构的语法变体,例如 s [...] = '...'。)

因此,与@raiph 的回答相比,这是我的答案:

my @tracks = <Foo Ba(r B^az>.map: { S:g / <[\(^]> // };

仅此而已。没有其他的。让我们从里到外剖析它:

这部分:/ <[\(^]> /是一个正则表达式,匹配一个字符,只要它是左括号(由\(表示)或脱字符(^ ).当它们进入尖角 brackets/square 括号组合时,这意味着它是一个 Enumerated character class.

然后: S 在文档的副词部分引入 non-destructive substitution, i.e., a quoting construct that will make regex-based substitutions over the topic variable $_ but will not modify it, just return its value with the modifications requested. In the code above, S:g brings the adverb :g or :global (see the global adverb ) 播放,意思是(在替换的情况下) "please make as尽可能多的替换,最后的/标记替换文本的结尾,因为它与第二个/相邻,这意味着

S:g / <[\(^]> //

表示“请return$_的内容,但修改为删除所有与正则表达式<[\(^]>匹配的字符(替换为空字符串)"

在这一点上,我应该强调 Raku 中的正则表达式 真的 强大,并且阅读整个页面(可能best practices and gotchas 页面也是一个好主意。

接下来,.map 方法 documented here 将应用于任何 IterableListArray 及其所有类似项)和将 return 基于 Iterable 的每个元素的序列,由传递给它的 Code 改变。所以,像这样:

@x.map({ S:g / foo /bar/ })

本质上意味着 "请 return Seq @x 上每个项目的影响,通过将子字符串 foo 的任何外观替换为bar"@x 不会有任何改变)。 A nice place to start to learn about sequences and iterables would be here.

最后,我的one-liner

my @tracks = <Foo Ba(r B^az>.map: { S:g / <[\(^]> // };

可译为:

我有一个包含三个字符串元素的 List

Foo
Ba(r
B^az

(这将是您的“标题列表”的占位符)。获取该列表并生成第二个列表,其中包含其中的每个元素,但删除了字符“左括号”和“脱字符”的所有实例。

啊,并将结果存储在变量 @tracks 中(具有 my 范围)