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

I ran the following line of code with strange results.
$prevFlagBin |= $flagBin;
Before running this line the debugger said:
x ($prevFlagBin, $flagBin) 0 3221225472 1 3758096384
After it said this:
0 '37792;77?6' 1 3758096384
Also in the debugger I found:
DB<4> x 3221225472 | 3758096384 0 3758096384
Correct answer!

But
DB<6> x '3221225472' | '3758096384' 0 '37792;77?6'
So I figured it was going into character context.

So I tried:
DB<8> x 0 | '3221225472' | '3758096384' 0 3758096384
And that worked.
So I modified my code to:
$prevFlagBin = 0 | $prevFlagBin | $flagBin;
Which works.

So my question is, is this a perl bug?
Do I need to understand something about the context here?
Do I get a performance advantage by using '|=' since that would be fast in C?
Have I lost that advantage due to this?

Comments appreciated.

-HarveyK

update (broquaint): changed plain formatting => <code> tags

Replies are listed 'Best First'.
Re: Bug in perl bitwise or??
by shemp (Deacon) on May 21, 2003 at 21:29 UTC
    This is a result of Perl's loose typecasting. If perl thinks your operands should be treated as strings, it will operate accordingly. How did you set the initial values of those variables, and what do you do with them just before the |= happens?

    Its not a bug, more of a subtle result of loose typecasting. If you set the variables in string context, i.e.
    $prevFlagBin = "3221225472";
    It is treated as a string.
      You are possibly correct. I had populated the value with unpack and an A10 value in that position. However, I thought it was in numeric context since the debug statement just before it had no single quotes around it.

      By the way its v5.6.1 on HPUX.

      Thanks

        (Perhaps unfortunately) The "x" command in the Perl debugger determines whether to put quotes around a value based on whether the value matches /^\d+(\.\d*)?\Z/ (see dumpvar.pl), not based at all on whether or not Perl considers the value to be a string, a number (of one of several types), or both. For example:

        DB<1> x -1 0 '-1' DB<2> x 1e19 0 '1e+019' DB<3> x "123" 0 123
        "Go figure."

                        - tye
        One way to test my theory would be to, immediately before the |= , add zero to each variable. That would force numeric context for the addition, and perl would still consider the vars as numbers for the |=.
Re: Bug in perl bitwise or??
by leriksen (Curate) on May 22, 2003 at 00:46 UTC
    For a more complete discussion on Perl Value Types see Advanced Perl Programming, but to prarphrase from page 329 of my copy
    A scalar value (SV - arrays are AV, hashs are HV etc) will be made up internally of its current value, a count of the number of references to that scalar, and an internal bitmask that decribes the current 'type' or 'state' of the value. These types can be
    • IV(integer value)
    • NV(numeric or double)
    • PV(string or pointer value)
    • RV(reference)
    • PV(A|H|C|G)V is for array|hash|code|glob
    • PVMG for magic (blessed) references

    So what you need, to get away from
    0|value1|value2
    cruft is to force the scalar from type PV to IV

    and _my_ favorite way to do this is
    $value += 0;
    this also my favorite way to trim leading zeroes from digit 'strings' - better than some regex's I've seen

      Just to be slightly pedantic - saying 0 | $value produces a numeric value but doesn't actually alter $value. Writing $value |= 0 alters $value so it is numeric.