Dav*_*man 9 perl perl6 undefined-behavior sequence-points raku
我天真地想在Perl 6和Perl 5之间进行相当多的字面上的翻译,实际上却没有,因为后增量变量的处理方式不同。
Perl 6产生了理想的结果,即幻方:[[8,1,6],[3,5,7],[4,9,2]]
my @sq; my $n = 3; my $i = 1; my $x = $n/2; my $y = 0;
@sq[($i%$n ?? $y-- !! $y++) % $n][($i%$n ?? $x++ !! $x) % $n] = $i++ for 0..$n**2 - 1;
say join ' ', $_ for @sq;
Run Code Online (Sandbox Code Playgroud)
Perl 5中的“相同”代码不:[[8,1,3],[9,5,7],[4,6,2]]
$n = 3; $i = 1; $x = $n/2; $y = 0;
$sq[($i%$n ? $y-- : $y++) % $n][($i%$n ? $x++ : $x) % $n] = $i++ for 0..$n**2 - 1;
say join ' ', @$_ for @sq;
Run Code Online (Sandbox Code Playgroud)
如果将语句拆分,则两者都可以正常工作,并且所有增量和减量都在赋值之后完成,例如在Perl 5中:
for (0 .. $n**2 - 1) {
$sq[ $y%$n ][ $x%$n ] = $i;
$i%$n ? $y-- : $y++;
$x++ if $i%$n;
$i++;
}
Run Code Online (Sandbox Code Playgroud)
如果递增或递减操作的返回值是该操作之前的变量的值,则Perl 5似乎是错误的。但是对代码进行的实验表明,$i%$n条件的结果是差异的源头,因此貌似Perl 6可能以$i无法严格保证的方式依赖的值。
因此,与Perl 5相比,Perl 6能够使我感到惊讶的是,不是吗?
如果您在单个语句中修改并读取相同的变量,则Perl 5和Perl 6均无法保证已定义行为。
Perl 6提要在并行执行的上下文中讨论序列点,但我相信它们也适用于语句内的读写问题。
但总的来说,您根本无法依靠任何一种语言来依赖它。
看来Perl 5和Perl 6代码之间的区别在于Perl 5代码使用了$i早于Perl 6的更新。例如以下Perl 5代码:
my $n = 3;
my $i = 2;
my $x = 5/2;
my $y = -1;
my @sq;
$sq[ ($i % $n ? $y-- : $y++) % $n] [ ($i % $n ? $x++ : $x) % $n ] = $i++;
say "x = $x, y = $y";
Run Code Online (Sandbox Code Playgroud)
印刷:
x = 2.5, y = 0
Run Code Online (Sandbox Code Playgroud)
而相同的 Perl 6 代码:
my $n = 3;
my $i = 2;
my $x = 5/2;
my $y = -1;
my @a;
@sq[ ($i % $n ?? $y-- !! $y++) % $n][ ($i % $n ?? $x++ !! $x) % $n ] = $i++;
say "x = $x, y = $y";
Run Code Online (Sandbox Code Playgroud)
印刷
x = 3.5, y = -2
Run Code Online (Sandbox Code Playgroud)
因此,Perl 5 代码使用$i++右侧的更新值(即在左侧$i = 3进行计算,而 Perl 6 使用旧值来计算等式左侧的索引。$i % $n$i = 2