lis*_*tor 6 readonly match rakudo assign raku
我在 Rakudo 2016.07 中运行良好的操作类中有以下方法,但我刚刚安装了 2016.11,现在新的 Rakudo 说我的方法尝试分配给只读变量,我只是没有看到问题:
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";
}
Run Code Online (Sandbox Code Playgroud)
整个错误信息是
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
Run Code Online (Sandbox Code Playgroud)
什么语言规范发生了变化?请帮忙。谢谢。
================================================== ===
谢谢雷夫、克里斯托夫、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;
Run Code Online (Sandbox Code Playgroud)
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?
Run Code Online (Sandbox Code Playgroud)
小智 8
这里有两个问题,我将依次回答:
1) match tries to assign to read-only variable
它尝试将 $/ 设置为您已经在您的范围内并且为只读的。您可以简单地在语法的 $/ 签名中使用不同的名称。我看到您立即将其强制为 Str,那么为什么不让签名这样做:
method ptName (Str() $nameStr) { ... }
Run Code Online (Sandbox Code Playgroud)
2) why not in 2016.07?
新行为不是错误,它由核心团队决定当前行为是可取的 (编辑:实际上,经过进一步检查,旧行为似乎是一个错误,其中 .match 静默无法设置 $/ 如果它是只读的) .
所以更大的问题是为什么行为会发生变化?
虽然有一个明显的目标是保持行为不变,以便用户可以依赖它,但我们还需要改进内容并继续前进。它的工作方式是我们有一个巨大的测试套件,我们称之为 Roast。如果对代码进行了破坏测试的更改,则无法在当前语言中进行该更改,并且必须推迟到下一个语言版本发布(从那时起用户可以使用use v6.c或 其他方式仍然保持旧行为)。
但是,如果测试套件通过,则意味着任何更改都没有确定下来,我们可以在不等待下一个语言版本的情况下更改它。这就是这种情况,使用.match.
显然,我们不希望我们的用户在我们的测试套件中寻找经过测试的内容和未测试的内容,这就是为什么我们的文档遵循我们不记录烘焙未涵盖的内容的政策。
.match您使用的方法目前就是这种情况。我不确定你从哪里了解到它,因为在 9 月底我创建了一个文档问题,表明.match没有记录,所以它当时不在文档中,正在等待大修 lizmat 工作,这改变了咬你的行为。
所以我希望能回答一些问题。我确实理解这样的代码破坏是非常不幸的,我们希望尽可能少发生这种情况,但同时我们需要改进语言。希望随着实现的成熟,这些未经测试和未记录的功能会越来越少。
干杯,ZZ