Okay, for starters: list-operators are among the lowest-precedence things in perl, but only on their right side. You ask what that means: well, let's make it simple. Suppose that there is a listop called foo
. It doesn't matter what it does, but it's there. You can easily create such a thing with sub foo { map 10 * $_, @_ }
which returns each of its arguments multiplied by ten. That out of the way:
print 1, 2, 3;
is equivalent to print( 1, 2, 3 );
print foo 1, 2, 3;
is equivalent to print( foo( 1, 2, 3 ) );
print 1, foo 2, 3;
is equivalent to print( 1, foo( 2, 3 ) );
We can see that foo
gobbles up as much as it can on the right side -- only the end of the statement (so far...) can stop it. If we wrote @array = (1, foo 2, 3);
that would be equivalent to @array = (1, foo(2, 3) );
because of course ending surrounding parentheses still applies.
Since commas are also very low priority (just above "List operators (rightward)"), we can also put pretty much any kind of expression we want into the arguments to a listop -- this is just perl's way of making sure that we don't have to add parentheses most of the time. Math, bitwise operators, comparisons, even regex matches have higher priority.
The only things that do have lower-priority are the spelled-out logical connectives and
, or
, xor
, and not
. So if we write
foo 1, 2, 3 and 4;
that means (foo(1, 2, 3) and 4)
-- the arguments to foo
stop to the left of the and
. This seems silly in a contrived example, so let's turn it into a common perl idiom:
open $fh, '<', $filename or die "$! opening $filename";
which is equivalent to
(open($fh, '<', $filename) or die("$! opening $filename"));
which is actually exactly equivalent to (and compiles to)
die "$! opening $filename" unless open $fh, '<', $filename;
using the statement-modifier form of unless
(which isn't an operator at all, is allowed only once per statement, and only comes at the end of a statement, so it doesn't really engage in precedence at all, but you could consider it as "lower than lowest" precedence leftwards).
So anyway, returning to your original code sample -- the arguments to print
and just left of the and
, and to the right of the and
is a completely separate comma expression -- which does nothing at all because it's just a few constants 3 > 4
and "\n"
evaluated in void context.