TL;DR 由@jakar提交的问题已被jnthn修复。
(在更多测试和代码调查后重写。)
在使用:g
和嵌入式块时,对我(和可能也对您)来说,这似乎是一个错误。 $/
在某种程度上被破坏了。
本答案涵盖了以下内容:
聚焦问题
查看编译器源代码
搜索问题队列并/或提交新问题
聚焦问题
my &debug = {;} # start off doing no debugging
$_ = 'aa';
say m / {debug 1} 'a' {debug 2} /; debug 3; # 「a」
say $/ if m / {debug 1} 'a' {debug 2} /; debug 3; # 「a」
say m:x(2) / {debug 1} 'a' {debug 2} /; debug 3; # (「a」 「a」)
say $/ if m:x(2) / {debug 1} 'a' {debug 2} /; debug 3; # (「a」 「a」)
say m:g / {debug 1} 'a' {debug 2} /; debug 3; # (「a」 「a」)
say $/ if m:g / {debug 1} 'a' {debug 2} /; debug 3; # 「a」 <--- Uhoh
现在让
debug
输出有用的信息并运行第一对(无需使用正则表达式副词):
&debug = { say $_, $/.WHICH }
say m / {debug 1} 'a' {debug 2} /; debug 3;
say $/ if m / {debug 1} 'a' {debug 2} /; debug 3;
在这两种情况下都会得到相同的简单结果。匹配过程会创建一个Match对象,并一直使用同一个对象。
现在考虑使用“:x(2)”副词的两种变体:
say m:x(2) / {debug 1} 'a' {debug 2} /; debug 3;
say $/ if m:x(2) / {debug 1} 'a' {debug 2} /; debug 3;
这次匹配过程创建了一个
Match
对象,并在第一遍使用它,然后在第二遍使用第二个匹配对象,在第三遍使用第三个匹配对象,直到无法匹配第三个
'a'
(因此相应的
debug 2
没有被调用)。在
m..../.../
调用结束时,它创建了一个
List
对象并将
该对象绑定到
$/
。
接下来我们运行两个
:g
中的第一个案例:
say m:g / {debug 1} 'a' {debug 2} /; debug 3;
和 x:(2)
情况一样,我们尝试第三次匹配仍然失败。但是匹配过程并没有返回一个 List
而是返回一个 Match
对象,而且它是在第三次尝试中创建的。(这让我感到惊讶。)
最后是 "Uhoh" 情况:
say $/ if m:g / {debug 1} 'a' {debug 2} /; debug 3;
值得注意的是,预期的第三次通行似乎没有开始。
查看编译器源代码
探索相关的源代码可能是有价值的。如果您或其他读者感兴趣,以及这是否是一个错误,我将在此处写下相关内容,以便对正在修复问题的人有用。
据我所知,在正则表达式中的代码块会导致生成 AST 节点,在这里 插入一个子节点到该块中的语句之前,执行绑定操作:
:op('bind'),
QAST::Var.new( :name('$/'), :scope('lexical') ),
QAST::Op.new(
QAST::Var.new( :name('$¢'), :scope('lexical') ),
:name('MATCH'),
:op('callmethod')
)
我的理解是,它插入的代码绑定了词法符号$ /
到在运行块之前紧接着绑定到词法符号$ ¢
的对象上调用.MATCH
方法的结果。
文档中有一个关于$¢
的章节,我引用一句话:
$/
和$ ¢
之间的主要区别是作用域:后者仅在正则表达式内部具有值
我想知道为什么存在$ ¢
以及其他区别是什么。
继续阅读...
我看到了raku级别的.MATCH
。但它几乎什么都没做。所以我认为相关的代码是这里。
此时我会暂停。我可能会在以后的编辑中继续。
搜索问题队列和/或提交新问题
如果有人在接下来的几天内提供了答案,证明您展示的不是错误,或者已被视为错误,那么就可以了。
否则,请考虑自己搜索问题队列和/或在您认为最合适的问题队列(默认为/rakudo/rakudo/issues)中开始一个新问题。
我已经在编写本回答的过程中搜索了四个github.com问题队列:
我搜索了两个关键词,希望能发现一个已存在的问题(“global”和“publish”)。没有相关的匹配问题。也许你可以寻找其他你认为筛选器可能使用的关键词。
如果您要提交问题,请考虑添加您的测试用例、我的测试用例或其他变体,并将其转换为标准烤肉测试用例(如果您知道如何进行操作)。