Perl FAQ 4.2: How come Perl operators have different precedence than C operators?

Perl FAQ 4.2

How come Perl operators have different precedence than C operators?

Actually, they don't; all C operators have the same precedence in Perl as they do in C. The problem is with a class of functions called list operators, e.g. print, chdir, exec, system, and so on. These are somewhat bizarre in that they have different precedence depending on whether you look on the left or right of them. Basically, they gobble up all things on their right. For example,

    unlink $foo, "bar", @names, "others";

will unlink all those file names. A common mistake is to write:

    unlink "a_file" || die "snafu";

The problem is that this gets interpreted as

    unlink("a_file" || die "snafu");

To avoid this problem, you can always make them look like function calls or use an extra level of parentheses:

    unlink("a_file")  || die "snafu";
    (unlink "a_file") || die "snafu";

In perl5, there are low precedence ``and'', ``or'', and ``not'' operators, which bind less tightly than comma. This allows you to write:

    unlink $foo, "bar", @names, "others"    or die "snafu";

Sometimes you actually do care about the return value:

    unless ($io_ok = print("some", "list")) { } 

Yes, print() returns I/O success. That means

    $io_ok = print(2+4) * 5;

returns 5 times whether printing (2+4) succeeded, and

    print(2+4) * 5;
returns the same 5*io_success value and tosses it.

See the perlop(1) man page's section on Precedence for more gory details, and be sure to use the -w flag to catch things like this.

One very important thing to be aware of is that if you start thinking of Perl's $, @, %, and & as just flavored versions of C's * operator, you're going to be sorry. They aren't really operators, per se, and even if you do think of them that way. In C, if you write

    *x[i]
then the brackets will bind more tightly than the star, yielding
    *(x[i])
But in perl, they DO NOT! That's because the ${}, @{}, %{}, and &{} notations (and I suppose the *{} one as well for completeness) aren't actually operators. If they were, you'd be able to write them as *() and that's not feasible. Instead of operators whose precedence is easily understandable, they are instead figments of yacc's grammar. This means that:
    $$x[$i]

is really

    {$$x}[$i]

(by which I actually mean)

    ${$x}[$i]

and not

    ${$x[$i]}

See the difference? If not, check out perlref(1) for gory details.


Other resources at this site: