What is wrong with print (2 & 2) >> 1?
Asked Answered
S

2

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
Staffman answered 12/6, 2019 at 7:30 Comment(2)
Turn on warnings (perl -w)Aldine
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.Subdued
C
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.

Chokebore answered 12/6, 2019 at 7:37 Comment(2)
Or you could add parenthesis around the parameters, too, of course: print((2 & 2) >> 1, "\n");Unbelievable
@DavidKrupička Welcome :) Let me know if questions come upChokebore
M
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
Monotony answered 12/6, 2019 at 7:38 Comment(3)
Well, it's more idiomatic to add the omitted parens. But yeah, the idiomatic way of leaving them off is to use a unary +.Lass
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.Lass
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.Paring
C
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.

Chokebore answered 12/6, 2019 at 7:37 Comment(2)
Or you could add parenthesis around the parameters, too, of course: print((2 & 2) >> 1, "\n");Unbelievable
@DavidKrupička Welcome :) Let me know if questions come upChokebore

© 2022 - 2024 — McMap. All rights reserved.