Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Post-increment and variable re-use in a single statement, Perl 5 vs Perl 6

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?

like image 873
David Hoekman Avatar asked May 05 '19 16:05

David Hoekman


1 Answers

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.

like image 111
moritz Avatar answered Nov 16 '22 02:11

moritz