writch has asked for the wisdom of the Perl Monks concerning the following question:

I thought this would be a no-brainer. I've been using a command line version of this code explicitly entering the values to get the proper number to put into the debug_level value in nagios.cfg: perl -e 'printf("%d\n", 16|8);'. I got tired of typing it, so I wrote what i thought was a simple script:
#!/usr/bin/perl use strict; use warnings; # a simple script to produce the 'or' number required for the debug_le +vel setting # in nagios.cfg my $or; for my $x (@ARGV){ $or |= $x ; } printf("%d\n", $or); exit;
The results were NOT what I expected. I'd have been happier if they returned '42' instead of '96', but '24' is what is supposed to come out. Here's me running it in the debugger:
perl -d or 16 8 Loading DB routines from perl5db.pl version 1.37 Editor support available. Enter h or 'h h' for help, or 'man perldebug' for more help. main::(or:9): my $or; DB<53> n main::(or:10): for my $x (@ARGV){ DB<53> n main::(or:11): $or |= $x ; DB<53> x $or, $x 0 undef 1 16 DB<54> x $or|$x 0 16 DB<55> n main::(or:11): $or |= $x ; DB<55> x $or, $x 0 16 1 8 DB<56> x $or|$x 0 96 DB<57> x 16|8 0 24 DB<58> n main::(or:14): printf("%d\n", $or); DB<58> n 96 main::(or:16): exit;
It's mystified the other perl programmer at my office as well. What's going on here?

Replies are listed 'Best First'.
Re: Counter Intuitive Code
by Corion (Patriarch) on Mar 27, 2019 at 14:41 UTC

    What you get is the string-biwise-or, not the number-bitwise-or:

    perl -wle "print '16'|'8'" 96 perl -wle "print '1'|'8'" 9

    If you tell Perl that you want the things to be really treated as numbers, the bitwise-or operator acts on the numerical representations:

    perl -wle "print 0+'16'|0+'8'" 24

    Prefixing 0+ in front of an expression is the canonical way in Perl to make a value be treated more as a number.

Re: Counter Intuitive Code
by roboticus (Chancellor) on Mar 27, 2019 at 17:41 UTC

    writch:

    As has been mentioned, you're getting the "string" bitwise conversion. Since you want to use numeric, just change the line:

    my $or;

    to:

    my $or = 0;

    This way, since you'll have a numeric value in $or, perl will convert the operands to integers before doing the '|', and you'll get the desired numeric version.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

Re: Counter Intuitive Code (use feature 'bitwise')
by LanX (Saint) on Mar 27, 2019 at 23:23 UTC
    FWIW, seems nobody mentioned it yet, but there is a feature to make bitwise or operate on numbers only.

    see perlop#Bitwise-Or-and-Exclusive-Or

    #!/usr/bin/perl use strict; use warnings; use feature 'bitwise'; no warnings 'experimental::bitwise'; my $or; for my $x (@ARGV){ $or |= $x ; } printf("%d\n", $or); exit;
    C:/Perl_524/bin\perl.exe d:/pm/bitwise_or.pl 16 8 24

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

    update

    and I agree it's counter intuitive because it's normal in Perl to have dedicated operators and expect automatic type casting. Here Perl is rather acting like JS.

Re: Counter Intuitive Code
by VinsWorldcom (Prior) on Mar 27, 2019 at 15:02 UTC

    Just wrap $x in int()?

    $or |= $x ; #change to => $or |= int($x);
Re: Counter Intuitive Code
by LanX (Saint) on Mar 27, 2019 at 14:43 UTC
    Quick diagnostic:

    debugger is bad with lexicals and multiline commands.

    Can't check now...

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: Counter Intuitive Code
by vr (Curate) on Mar 27, 2019 at 22:19 UTC

    Another alternative would be to tell Perl to DWIM, by putting her into position to use her own brains instead of bothering you to micromanage -- the position is "can't tell string from number? very well, here's no numbers for you but just a string, and don't come back until you figure it out yourself": eval join'|', @ARGV

    (it was a joke, btw)

      eval join'|', @ARGV

      While that works, it is dangerous to directly eval user input. eval has the full power of the perl compiler behind it.

      Of course, in this use case, the user is also using the Perl debugger, which is equally dangerous.

      Always remember, tools of great power come with great responsibility.