Make bitwise operators always use numeric context

[This feature is no longer experimental, starting in v5.28. Declaring use 5.28 automatically enables them.]

Most Perl operators force their context on the values. For example, the numeric addition operator, +, forces its values to be numbers. To “add” strings, you use a separate operator, the string concatenation operator, . (which looks odd at the end of a sentence).

The bitwise operators, however, look at the value to determine their context. With a lefthand value that has a numeric component, the bitwise operators do numeric things. With a lefthand value that’s a string, the bit operators become string operators. That’s certainly one of Perl’s warts, which I’ll fix at the end of this article with a new feature from v5.22.

Consider this demonstration where the operator is the same but the type of argument changes:

my $number  = 0x80 ^ 0x20;
my $mixed   = "P"  ^ 0x20;
my $string  = "P" ^ " ";

print <<"HERE";
Number is $number
Mixed  is $mixed
String is $string
HERE

The result is different in each case:

Number is 160
Mixed  is 32
String is p

This leads to the joke about the difference between Perl and perl being one bit:

% perl -e 'printf "[%b]\n", ord("perl" ^ "Perl")'
[100000]

This is a problem if you want a particular context. You have to force either the string or numeric context. If either of the operands has a numeric component (see Create your own dualvars) it’s a numeric operation:

"$var" ^ "$var2"
$var + 0 ^ $var2

Or, you can skip all this messiness with a new experimental feature from v5.22. The bitwise feature makes the bitwise operators always work in numeric context. You have to import this one explicitly because it’s not automatically imported as part of the default new feature set:

use v5.22;
use feature qw(bitwise);
no warnings qw(experimental::bitwise);

my $number = 0x80 ^ 0x20;
my $mixed  = "P"  ^ 0x20;
my $string = "P" ^ " ";

print <<"HERE";
Number is $number
Mixed  is $mixed
String is $string
HERE

Now the output for the last case is 0 instead of p:

Number is 160
Mixed  is 32
String is 0

This is probably what you want most of the time. And, if you don't want this, do you really want a bitwise operator?