1

I am just wondering what happens with that piece of code. Why the result is incorrect only when printed directly, why is the newline ignored?

user@host_09:22 AM: perl
print 2 >> 1, "\n";
print 2 & 2, "\n";
print (2 & 2) >> 1, "\n";
1
2
2user@host_09:22 AM: perl
$a = (2 & 2) >> 1;
print "$a\n";
1
zdim
  • 64,580
  • 5
  • 52
  • 81
  • Turn on warnings (`perl -w`) – Mat Jun 12 '19 at 07:34
  • 3
    Just for completeness: for the general case you should turn on warnings with the warnings module (`use warnings;` or `-Mwarnings`), not `-w`, as `-w` also can affect modules you use that you have no control over. – Grinnz Jun 12 '19 at 15:13

2 Answers2

6

Perl interprets the parentheses as function arguments marker, as you can verify with

perl -MO=Deparse,-p -e 'print (2 & 2) >> 1'

Output:

(print(2) >> 1);

The canonical way is to precede the left parenthesis with a +:

print +(2 & 2) >> 1
choroba
  • 231,213
  • 25
  • 204
  • 289
  • Well, it's more idiomatic to add the omitted parens. But yeah, the idiomatic way of leaving them off is to use a unary `+`. – ikegami Jun 12 '19 at 12:18
  • It's worth noting that unary `+` work with any kind of values, not just numbers. It literally has no effect on the value passed to it. – ikegami Jun 12 '19 at 12:19
  • I like the -MO=Deparse suggestion, but if you don't mind, I marked zdim's post as the answer, because it is slightly more detailed. – David Krupička Jun 13 '19 at 08:38
5

When you print it with warnings it becomes clear(er)

perl -we'print (2 & 2), "\n"'

says

print (...) interpreted as function at -e line 1.
Useless use of a constant ("\n") in void context at -e line 1.

It works out print (2&2) as a function call to print and duly prints 2 (no newline!), and then it keeps evaluating the comma operator, with "\n" in void context next, which it also warns us about.

With >> 1 also there, the return 1 of print (2&2) (for success) is bit shifted to 0, which disappears into the void, and we get another "Useless use of ... in void context."

One fix is to add a + since what follows it must be an expression

perl -we'print +(2 & 2) >> 1, "\n"'

Or, make a proper call to print, with parenthesis around the whole thing

perl -we'print((2 & 2) >> 1, "\n")'

Both print a line with 1.

This is mentioned in print, and more fully documented in Terms and List operators and in Symbolic Unary operators, both in perlop. For another, related, example see this post.


 It also warns about it as it is likely an error -- with a space before parens; no space, no warning.

zdim
  • 64,580
  • 5
  • 52
  • 81