A line of code that I naively thought would translate fairly literally between Perl 6 and Perl 5 in fact did not, due to differences in how a post-increment variable is being handled.
This Perl 6 yields the desired result, a magic square: [[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;
The 'same' code in Perl 5 does not: [[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;
Both work correctly if the statement is split up, and all the increments and decrements are done after the assignment, e.g. in Perl 5:
for (0 .. $n**2 - 1) {
$sq[ $y%$n ][ $x%$n ] = $i;
$i%$n ? $y-- : $y++;
$x++ if $i%$n;
$i++;
}
If the return value of an increment or decrement operation is value of the variable before the operation, then Perl 5 would be seem to be in the wrong. But experimenting with the code showed that the result of the $i%$n
conditions was the source of the difference, so seemingly Perl 6 may be relying upon the value of $i
in a way that is not strictly guaranteed.
Thus I should have been more surprised that Perl 6 worked, than that Perl 5 didn't?
Both Perl 5 and Perl 6 do not promise defined behavior if you modify and read the same variable within a single statement.
The Perl 6 synopses talk about sequence points in the context of parallel execution, but I believe they also apply to the read+write problem within statements.
But in general, you simply cannot rely on this in either language.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With