2016-12-05 100 views
3

我有在Rakudo 2016.07行之有效的动作类下面的方法,但我刚安装了2016.11现在新Rakudo说我的方法试图将分配给只读varible,我只是不明白的问题:perl6 rakudo 2016.11匹配尝试分配给只读变量,为什么不在2016.07?

method ptName ($/) { 
    my $nameStr = $/.Str, my $lastName, my $firstName; 
    my $newMatch # this is line 182; 
        # Cannot assign to a readonly variable or a value 
     = $nameStr.match(/ \" (<alpha>+) .*? \, \s* (<alpha>+) .*? \" /); 
    $lastName = $newMatch[0]; 
    $firstName = $newMatch[1]; 
    make "$lastName $firstName"; 
} 

整个错误消息是

Cannot assign to a readonly variable or a value 
    in method ptName at /home/lisprog/Binary/grammar.pl line 182 
    in regex ptName at /home/lisprog/Binary/grammar.pl line 151 
    in regex TOP at /home/lisprog/Binary/grammar.pl line 137 
    in block <unit> at /home/lisprog/Binary/grammar.pl line 217 

什么语言规范变化?请帮忙。谢谢。

============================================== =======

谢谢raiph,克里斯托夫,ZZ!我不知道如何用正确的格式添加长评论。所以,我正在给自己的帖子添加评论。

我写了一个测试程序,现在看来,如果我没有在方法签名使用(/ $),因为我必须使用.match的方法中,我不能长期做任何事情。我做错了什么?下面是测试程序和结果:

测试程序:

grammar test { 
    regex TOP { <foo><bar> } 
    regex foo { :i \s* foo \s* } 
    regex bar { :i \s bar \s* } 
} 

class actTest { 
    method foo ($x) { # program fails if I use $/ in signature 
     print "1 "; say $x; # how to combine the 2 and show $x as match? 
     print "2 "; say $x.WHAT; 
     my $newStr = $x.Str; 
     print "3 "; say $newStr; 
     my $newMatch 
      = $newStr.match(/:i(f)(oo)/); # adverb cannot be outside? 
     print "4 "; say $newMatch.WHAT; 
     print "5 "; say $newMatch; 
     print "6 "; say $/; 
     my $oo = $newMatch[1].Str; 
     print "10 "; say $oo; 
     my $f = $newMatch[0].Str; 
     print "11 "; say $f; 
     my $result = $oo ~ $f; 
     print "12 "; say $result; 
     make $result; # now I cannot make anything; huh??? 
    } 
    method TOP ($/) { 
     print "8 "; say $<bar>; 
     print "9 "; say $<foo>.made; # failed, method 'foo' makes nothing 
     make $<bar> ~ $<foo>.made; 
    } 
} 

my $m = test.parse("Foo bar", actions => actTest.new); 
print "7 "; say $m; 

而结果:

1 「Foo 」 
2 (Match) 
3 Foo 
4 (Match) 
5 「Foo」 
0 => 「F」 
1 => 「oo」 
6 「Foo」 
0 => 「F」 
1 => 「oo」 
10 oo 
11 F 
12 ooF 
1 「Foo」 
2 (Match) 
3 Foo 
4 (Match) 
5 「Foo」 
0 => 「F」 
1 => 「oo」 
6 「Foo」 
0 => 「F」 
1 => 「oo」 
10 oo 
11 F 
12 ooF 
8 「 bar」 
9 (Any) 
Use of uninitialized value of type Any in string context. 
Methods .^name, .perl, .gist, or .say can be used to stringify it to 
something meaningful. 
in method TOP at matchTest.pl line 28 
7 「Foo bar」 
foo => 「Foo」 
bar => 「 bar」 
+0

我隐约想起这件事。当你写'method ptName($/is copy){'?那么'方法ptName($ /是rw){'? – raiph

+0

谢谢你raiph!当我在任何$ a = $ someString.match()上使用($/is copy)时,程序运行,但是没有给出有意义的$ a [0]或$ a [1];当我使用($ /是rw)时,发生新的错误,并且它说“参数'$ /'预期可写容器,但获得了匹配值”。我在Rakudo 2016.07中没有这个问题。我认为2016.11有些事情会爆发。上次我试图报告错误时,邮件以无法投递的方式反弹回来。谢谢。 – lisprogtor

+0

@lisprogtor:人们似乎能够再次打开门票,参见http://perl6.fail/ – Christoph

回答

3

这里有两个问题,我会回答每个反过来:

1)match tries to assign to read-only variable

它试图设置$ /,你已经在你的范围和为只读。您可以简单地在语法的$ /的签名中使用不同的名称。我看到你强迫它向海峡向右走,所以为什么不让签名做到这一点:

method ptName (Str() $nameStr) { ... } 

2)why not in 2016.07?

新的行为是不是一个错误,它是由核心团队决定当前 行为是可取的 (编辑:实际上,在进一步检查看来,旧的行为是一个错误,其中.match默默无法设置$ /如果它只是只读)。

所以更大的问题是为什么行为改变了?

虽然有一个明显的目标是保持行为相同,以便用户可以依靠它,但我们还需要改进内容并向前迈进。它的工作方式是我们有一个huge test suite we call Roast。如果对代码进行了改变以打破测试,那么就不能用当前语言进行更改,并且必须推迟到下一次语言版本发布(因为用户可以使用use v6.c或其他任何仍旧会出现的旧行为)。

但是,如果测试套件通过,那意味着任何未更改的内容都可以被修改,我们可以在不等待下一次语言版本的情况下进行更改。情况就是这样,与.match。很显然,我们不希望我们的用户通过我们的测试套件搜索什么被测试和什么不是,这就是为什么我们的文档遵循的政策,我们没有记录的东西,不包括在烤。

目前,您已使用.match方法。我不确定你在哪里了解到这一点,截至9月底I created a doc Issue表明.match没有记录,所以它不在文档中,然后等待lizmat的检修工作,这改变了那个位的行为您。

所以我希望能回答一些问题。我确实理解这样的代码非常不幸,我们希望尽可能少地发生,但同时我们需要改进语言。希望随着实现的成熟,这些未经测试和未记录的功能将越来越少。

干杯, ZZ

+0

这个决定的理由是什么?个人而言,我更喜欢陈旧的行为 – Christoph

+0

@Christoph,我没有参与这个变化,所以我无法肯定地回答。您可以搜索[开发通道日志](https://irclog.perlgeek.de/perl6-dev/search/?nick=&q=match)(大约在十月份)或跳到[开发者通道](https ://webchat.freenode.net/?channels =#perl6-dev)并尝试捕获完成所有工作的lizmat ++。 –

+0

@Christoph,但玩弄了代码,我发现.match甚至在更改之前设置了$ /,它只是在$ /是只读时以静默方式失败,导致意外的行为。所以我想这只是一个错误修复,而不是行为改变。 –

1

git blame src/core/Str.pm,lizmat在这个十月的工作。 Str.match现在将调用调用块的词法$/,当它显然没有这样做。

这意味着Str.match将返回其结果两次:第一次作为其返回值,第二次通过设置$/带外。虽然通过~~正则表达式的应用做到这一点,以及(这是必要的,这样你可以使用语法糖像$0$<foo>),我不相信Str.match应该。 如果以前没有这样做,我怀疑它可能是一个错误:要么报告它,要么在Freenode上询问#perl6

正如Zoffix所指出的那样,这是旧的行为,因为$/总是应该设置,但无法这样做只是没有触发异常。

+0

谢谢Christoph!我不确定你的意思是“不需要这样做”。 – lisprogtor

+0

@lisprogtor:cf'say“foo”.match(/ f /)。WHICH === $ /。WHICH';我将澄清... – Christoph

+0

FWIW,~~也返回匹配对象:my $ res ='foo'~~ /.+/;说$ res –

0

我要感谢ZZ,克里斯托夫,raiph和关注类贷款在帮助我花费宝贵的时间。我的问题已经通过

(1)使用除$ /以外的方法签名和 (2)使用签名匹配对象来制作而不是使用$ /来制作。

请同时参阅答案在https://stackoverflow.com/posts/41027321/revisions

非常感谢您!