gpt4 book ai didi

regex - "inconsistent"在正则表达式中使用代码块时的匹配结果 [Raku]

转载 作者:行者123 更新时间:2023-12-03 09:27:38 27 4
gpt4 key购买 nike

在检查和测试正则表达式的各个方面时,我偶然发现了一种奇怪且“不一致”的行为。我试图在正则表达式中使用一些代码,但同样的行为也适用于使用 void 代码块。
尤其是最让我感动的是,当我互换 :g 和 :x 修饰符时,匹配结果的差异。

以下代码片段描述了“不一致”的行为。

首先没有代码块:

use v6.d;

if "test1 test2 test3 test4" ~~ m:g/ (\w+) / {
say ~$_ for $/.list;
}

结果:
test1
test2
test3
test4

然后使用 :g 修饰符和代码块:
use v6.d;

if "test1 test2 test3 test4" ~~ m:g/ (\w+) {} / {
say ~$_ for $/.list;
}

结果:
test4

最后使用 :x 修饰符和代码块
use v6.d;

if "test1 test2 test3 test4" ~~ m:x(4)/ (\w+) {} / {
say ~$_ for $/.list;
}

结果:
test1
test2
test3
test4

我预计这三个结果是相同的,但我感到非常惊讶。

关于这种行为有什么解释吗?

最佳答案

TL;DR Issue filed by @jakarfixed by jnthn .

(经过更多测试和代码探索后重写。)

这在我(可能是你)看来就像一个错误。 $/使用 :g 时不知何故变得古怪和一个嵌入式 block 。

这个答案包括:

  • 关注问题
  • 看编译器的源码
  • 搜索问题队列和/或提交新问题

  • 解决问题
    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 location of object bound to `$/`

    say m / {debug 1} 'a' {debug 2} /; debug 3; # 「a」
    # 1Match|66118928
    # 2Match|66118928
    # 「a」
    # 3Match|66118928

    say $/ if m / {debug 1} 'a' {debug 2} /; debug 3; # 「a」
    # 1Match|66119072
    # 2Match|66119072
    # 「a」
    # 3Match|66119072

    两种情况下的结果相同。匹配过程创建一个 Match对象并坚持同一个。

    现在 :x(2) 的两个变体副词:
    say       m:x(2) / {debug 1} 'a' {debug 2} /; debug 3; # (「a」 「a」)
    # 1Match|66119936
    # 2Match|66119936
    # 1Match|66120080
    # 2Match|66120080
    # 1Match|66120224
    # (「a」 「a」)
    # 3List|67612624

    say $/ if m:x(2) / {debug 1} 'a' {debug 2} /; debug 3; # (「a」 「a」)
    # 1Match|66120368
    # 2Match|66120368
    # 1Match|66120512
    # 2Match|66120512
    # 1Match|66120656
    # (「a」 「a」)
    # 3List|67612672

    这次匹配过程创建了一个 Match对象并坚持使用它进行一次传递,然后是第二次匹配对象进行第二次传递,最后是第三次匹配对象进行第三次传递,直到它无法匹配第三次 'a' (因此相应的 debug 2 不会被调用)。在 m.../.../ 的末尾调用它创建了一个 List对象并将其绑定(bind)到 $/ .

    接下来我们运行两个 :g 中的第一个案例:
    say       m:g    / {debug 1} 'a' {debug 2} /; debug 3; # (「a」 「a」)
    # 1Match|66119216
    # 2Match|66119216
    # 1Match|66119360
    # 2Match|66119360
    # 1Match|66119504
    # (「a」 「a」)
    # 3Match|66119504

    喜欢 x:(2)案例,我们尝试第三次,但失败了。但匹配过程不返回 List而是一个 Match目的。它是在第三遍中创建的。 (这让我感到惊讶。)

    最后,还有“Uhoh”案例:
    say $/ if m:g    / {debug 1} 'a' {debug 2} /; debug 3; # 「a」 <--- Uhoh
    # 1Match|66119648
    # 2Match|66119648
    # 1Match|66119792
    # 2Match|66119792
    # 「a」
    # 3Match|66119792

    值得注意的是,预期的第三遍似乎没有开始。

    查看编译器的源代码

    探索相关的源代码是有值(value)的,这似乎是合理的。我将在这里写下它,以防您或其他读者感兴趣,并且如果这是一个错误并且我所写的内容对修复它的人感兴趣。

    在正则表达式中处理代码块会导致生成 AST 节点 here在执行绑定(bind)操作的 block 中的语句之前插入一个子节点:
                        :op('bind'),

    QAST::Var.new( :name('$/'), :scope('lexical') ),

    QAST::Op.new(
    QAST::Var.new( :name('$¢'), :scope('lexical') ),
    :name('MATCH'),
    :op('callmethod')
    )

    我对上面的阅读是它插入了绑定(bind)词法 $/ 的代码。 .MATCH 结果的符号对绑定(bind)到词法 的对象的方法调用在 block 中运行代码之前的符号。

    该文档有 a section on ;我引用一句话:

    The main difference between $/ and is scope: the latter only has a value inside [a] regex



    我想知道为什么 存在以及存在哪些其他差异。

    继续...

    我看到有 a raku level .MATCH .但它几乎没有任何作用。所以我认为相关的代码是 here .

    在这一点上,我会暂停。我可能会在以后的编辑中继续。

    搜索问题队列和/或提交新问题

    如果有人在接下来的几天内提出了一个答案,证明您所展示的不是错误,或者已经作为错误提交,那么就足够公平了。

    否则,请考虑自己搜索问题队列和/或在您认为最合适的任何问题队列中开始新问题(默认为/rakudo/rakudo/issues)。

    我已经搜索了四个 github.com 问题队列,我认为这是写这个答案的一部分:
  • https://github.com/rakudo/rakudo/issues
  • https://github.com/Raku/old-issue-tracker/issues
  • https://github.com/perl6/nqp/issues
  • https://github.com/moarvm/moarvm/issues

  • 我搜索了两个关键字,希望能发现一个现有问题(“全局”和“发布”)。没有相关的匹配问题。也许您还可以查找您认为文件管理器可能使用的其他关键字。

    如果您确实提出了问题,请考虑添加您的测试,或者我的测试或其他一些变体,如果您知道如何执行此操作,则转换为标准烘焙测试用例。

    关于regex - "inconsistent"在正则表达式中使用代码块时的匹配结果 [Raku],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60587025/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com