Search code examples
perloperations

Dot at the beginning of a "print" statement?


I've come across something odd while using a Perl script. It's about using a dot giving different results.

perlop didn't turn anything up, or perhaps I just blew past it. I was looking at Operator Precedence and Associativity

print "I'd expect to see 11x twice, but I only see it once.\n";
print (1 . 1) . "3";
print "\n";
print "" . (1 . 1) . "3\n";
print "Pluses: I expect to see 14 in both cases, and not 113, because plus works on numbers.\n";
print (1 . 1) + "3";
print "\n";
print "" + (1 . 1) + "3\n";

Putting quotes at the start is an acceptable workaround to get what I want, but what is happening here with the order of operations that I'm missing? What rules are there to be learned?


Solution

  • When you put the first argument to print in parentheses, Perl sees it as function call syntax.

    So this:

    print (1 . 1) . "3";
    

    is parsed as this:

    print(1 . 1)  . "3";
    

    or, equivalently:

    (print 1 . 1) . "3";
    

    Therefore, Perl prints "11", then takes the return value of that print call (which is 1 if it succeeded), concatenates 3 to it, and - since the whole expression is in void context - does absolutely nothing with the resulting 13.

    If you run your code with warnings enabled (via -w on the command line or the use warnings; pragma), you will get these warnings identifying your error:

    $ perl -w foo.pl
    print (...) interpreted as function at foo.pl line 2.
    print (...) interpreted as function at foo.pl line 6.
    Useless use of concatenation (.) or string in void context at foo.pl line 2.
    Useless use of addition (+) in void context at foo.pl line 6.
    

    As Borodin points out in the comment below, you shouldn't rely on -w (or the in-code equivalent $^W); production code should always make use of the warnings pragma, preferably with use warnings qw(all);. While it wouldn't matter in this particular instance, you should also use strict;, although requesting modern features via useversion; for a Perl version of 5.11 or higher automatically turns on strict as well.