语法行为是否在6.c和6.d之间中断?

p6s*_*eve 10 perl6 raku

我的语法在6.c(2018.01)中可以正常工作-我无法在6.d(2019.03.01)中获得稳定的输出。

当我打开Grammar :: Tracer(nice!)时,模式似乎是一致的。

但是使用相同的输入'm / s',我的输出会随机经过一系列结果,例如 ... * m / s = m.True * m / s = True.m * m / s = s-1.True * m / s = ms-1(这是我想要的那个,不在乎顺序)

我对unam =>?s有怀疑吗?// 是吗 匹配对象的内容(请参阅调试代码)-跟踪器在每个分支中仅显示一个unam匹配项。

欢迎所有建议!

#!/usr/bin/env perl6

sub get-dime( $dime-str ) { 
        use Grammar::Tracer;

        my $unit-names = '|m|s';

        grammar UnitGrammar {
            token TOP     { <dim> <divi> <den> }
            token divi    { \/ }
            token dim     { <unam> }
            token den     { <unam> }
            token unam    { <$unit-names> }
        }    
        class UnitActions {
            method TOP($/)     { make $/.values.[0].made~'.'~$/.values.[1].made }
            method dim($/)     { make ~$<unam> }
            method den($/)     { make ~$<unam>~'-1' }
            method divi($/)    { make True }
        }    

        my $match = UnitGrammar.parse($dime-str, :actions(UnitActions));

        #[[ verbose for debug (also uncomment #use Grammar::Tracer)
        say "$match=", $match.made;
        say "--------------------";
        say $match.values;
        say $match.values.[0].made;
        say $match.values.[1].made;
        #]]  

        return $match.made if $match.so;
}
say $*PERL.compiler.version;
say get-dime( 'm/s' );
Run Code Online (Sandbox Code Playgroud)

禁止 在此处输入图片说明

rai*_*iph 10

@Håkon为游戏命名。您已准备好在跑道上着陆。我让我们靠近果岭,但在崎rough不平的地方。@ugexe抓住了球。@Håkon跳过了这个洞,移至下一个发球区域并打入一个洞。所以我想我要写赛后总结了。


这不是6.cVS 6.d

潜在的问题是,哈希被指定为以随机顺序列出其键/值对。在较早的编译器中,哈希列表实现以固定顺序返回键/值对。然后,去年samcv为MoarVM实现了哈希随机化。它破坏了错误地依赖哈希顺序的代码。

因此,以下代码-自2018.05开始在Rakudo / MoarVM上-随机显示(a b)(b a)

say .values given { apple => 'a', bananas => 'b' }
Run Code Online (Sandbox Code Playgroud)

您的代码正在调用.values一个Match对象。

调用该方法通常可以归结为以下效果:

say .values given ( apple => 'a', bananas => 'b', 0, 1, 2 ) .Capture
Run Code Online (Sandbox Code Playgroud)

将会显示一个列表,列表以0 1 2(它们是位置,因此它们以正确的顺序首先显示)开头,然后是a bor b a(它们的名称,因此它们以随机顺序显示最后一个)开头。

这又是因为a Match是的子类,Capture并且.values从该类继承其方法。正如其文档所说:

返回Seq包含所有位置值,后跟所有命名参数值的。

您的代码中没有位置捕获。因此,您所看到的只是命名捕获的值。但是它们当然在列表中,因此出现在索引.[0].[1]等下,这可能会诱使您认为它们是有序的(结合事实,在早期的Rakudos中,它们的随机顺序实际上是固定的)。

.caps对此进行了改进,因为它根据输入中的匹配位置对值进行排序。这将确保命名捕获的值列表的稳定排序-前提是所有捕获都不共享匹配的位置:

say .caps given 'foo' ~~ / $<alias>=<ident> /
Run Code Online (Sandbox Code Playgroud)

将随机显示(alias => ?foo? ident => ?foo?)(ident => ?foo? alias => ?foo?)

我的第一个答案

作为记录,这是此答案的第一个版本:

在这里,我想打高尔夫球的路要走得很远。

grammar {
  token TOP { <one> <two> }
  token one { 1 }
  token two { 2 }
}.parse('12').values.say;
Run Code Online (Sandbox Code Playgroud)

在tio.run上运行的当前版本v2018.04中,此显示可靠(?1? ?2?)。在glot.io上运行的当前版本v2018.12中,这会生成或,(?1? ?2?)或者(?2? ?1?)在两者之间随机变化。

我不知道这是否是错误。调查仍在继续,但我认为我会将其发布为初步答案。


Håk*_*and 6

我不确定$/.values应该返回什么顺序(我得到了您所描述的随机顺序),而是使用了$/.values

method TOP($/)     {
     make $<divi> ?? $/.values.[0].made~'.'~$/.values.[1].made
                  !! $/.values.[0].made
}
Run Code Online (Sandbox Code Playgroud)

您可以使用try $/.caps

method TOP($/)     {
    make $<divi> ?? $/.caps.[0].value.made~'.'~$/.caps.[2].value.made
                 !! $/.caps.[0].value.made
}
Run Code Online (Sandbox Code Playgroud)

至少这对我有用。