|
Perl4-to-Perl5 traps involving precedence order.
Perl 4 has almost the same precedence rules as Perl 5 for the operators that they both have.
Perl 4 however, seems to have had some inconsistencies that made the behavior differ from what
was documented.
- * Precedence
-
LHS vs. RHS of any assignment operator. LHS is evaluated first in perl4, second in perl5;
this can affect the relationship between side-effects in sub-expressions.
@arr = ( 'left', 'right' );
$a{shift @arr} = shift @arr;
print join( ' ', keys %a );
# perl4 prints: left
# perl5 prints: right
|
|
- * Precedence
-
These are now semantic errors because of precedence:
@list = (1,2,3,4,5);
%map = ("a",1,"b",2,"c",3,"d",4);
$n = shift @list + 2; # first item in list plus 2
print "n is $n, ";
$m = keys %map + 2; # number of items in hash plus 2
print "m is $m\n";
# perl4 prints: n is 3, m is 6
# perl5 errors and fails to compile
|
|
- * Precedence
-
The precedence of assignment operators is now the same as the precedence of assignment.
Perl 4 mistakenly gave them the precedence of the associated operator. So you now must
parenthesize them in expressions like
/foo/ ? ($a += 2) : ($a -= 2);
|
|
Otherwise
/foo/ ? $a += 2 : $a -= 2
|
|
would be erroneously parsed as
(/foo/ ? $a += 2 : $a) -= 2;
|
|
On the other hand,
now works as a C programmer would expect.
- * Precedence
-
is now incorrect. You need parentheses around the filehandle. Otherwise, perl5 leaves the
statement as its default precedence:
open(FOO || die);
# perl4 opens or dies
# perl5 opens FOO, dying only if 'FOO' is false, i.e. never
|
|
- * Precedence
-
perl4 gives the special variable, $: precedence, where perl5 treats $::
as main package
$a = "x"; print "$::a";
# perl 4 prints: -:a
# perl 5 prints: x
|
|
- * Precedence
-
perl4 had buggy precedence for the file test operators vis-a-vis the assignment
operators. Thus, although the precedence table for perl4 leads one to believe -e $foo
.= "q" should parse as ((-e $foo) .= "q"), it
actually parses as (-e ($foo .= "q")). In perl5, the precedence is as
documented.
-e $foo .= "q"
# perl4 prints: no output
# perl5 prints: Can't modify -e in concatenation
|
|
- * Precedence
-
In perl4, keys(), each() and values() were special high-precedence operators that
operated on a single hash, but in perl5, they are regular named unary operators. As
documented, named unary operators have lower precedence than the arithmetic and
concatenation operators + - ., but the perl4 variants of these operators
actually bind tighter than + - .. Thus, for:
%foo = 1..10;
print keys %foo - 1
# perl4 prints: 4
# perl5 prints: Type of arg 1 to keys must be hash (not subtraction)
|
|
The perl4 behavior was probably more useful, if less consistent.
|
|