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

I have encountered a very strange thing, and I'm wondering if anyone else has seen it, and if so what he or she might have done about it. The most frustrating aspect of this is that I cannot reproduce the problem with a short program that contains the same code.

As background, allow me to say that I've been working with Perl for some 20 years. I'm not a newbie, and I've eliminated many possibilities already. I'm open to the possibility that I'm missing something fundamental, but I'm as certain as a person can be that it's nothing basic.

The code is thus:

... $baz = $info{$key}; # $baz = unpack('H*', $baz); # $baz = pack('H*', $baz); print(STDOUT '[' . ($baz) . "]\n"); print(STDOUT '[' . (unpack('H*', $baz)) . "]\n" ); print(STDOUT '[' . ($baz eq 'true') . "]\n"); print(STDOUT '[' . ($baz eq 'false') . "]\n"); print(STDOUT '[' . ($baz eq 'default') . "]\n"); ...

With those unpack() and pack() calls commented out and when the value of $info{$key} is 'false' (that is, the string 'false'), the code in-place in the larger program yields:

[false] [66616c7365] [] [1] [1]

When I remove the comment markers (thus calling unpack() and then pack() in succession on the value), it yields the much more expected:

[false] [66616c7365] [] [1] []

Again, if I take these lines and make them into a short program by themselves, the unpack() / pack() dance is not necessary; the three 'eq' comparisons yield the second block of output, as expected.

So, we have a situation where (a) 'eq' is evaluating the same value to be equivalent to two different strings, and (b) an unpack() followed immediately by pack() is having an effect on the value, when that should not happen (at least, not with a template as simple as 'H*') since these two functions are mirrors of each other.

Has anyone ever seen the same kind of unexpected funniness with 'eq'? Does the fact that unpack() + pack() affects the value here tell us anything about the nature of the underlying data that is salient to understanding the unexpected 'eq' results? And, related, is there something about the inner operation of unpack() / pack() that sheds some light on this oddity?

Thanks in advance for any insight. I'm happy to provide additional detail that might help diagnose this.

Replies are listed 'Best First'.
Re: eq evaluates a variable as equal to two different strings
by Anonymous Monk on Jan 30, 2015 at 21:21 UTC
    Looks like an overload. So what is $info{$key}, where does it come from?

    Try this

    use Devel::Peek; Dump $info{$key};
    And post the output on the forum.

      Sure thing. $info{$key} is populated from some JSON fetched from an API call, then decoded, then parsed into perl data objects for handy use within my program.

      Here is the output from that added Dump call, just above the output I included before:

      SV = PVIV(0x1604e78) at 0x161f2e8 REFCNT = 1 FLAGS = (ROK) IV = 0 RV = 0x14b87a0 SV = PVMG(0x13d6ec0) at 0x14b87a0 REFCNT = 16 FLAGS = (PADMY,OBJECT,IOK,OVERLOAD,pIOK) IV = 0 NV = 0 PV = 0 STASH = 0x1438a90 "JSON::PP::Boolean" PV = 0x14b87a0 "" CUR = 0 LEN = 0 [false] [66616c7365] [] [1] [1]

      I take it that the presence of "OVERLOAD" among the flags confirms your suspicion. In parallel with posting this, I'll start reading what I can find, based on the hints in this additional output. Devel::Peek is new to me. Thanks for the pointer.

        Well, a quick read on how to interpret Devel::Peek info suggests that the output here explains why I was confused : the original value is not what it seemed it was, despite a variety of debug output to the contrary.

        I also (think) I see why the unpack() + pack() pair of calls have the 'magical' effect that they are having.

        The main thing for me is that this is no longer a mystery. I can see clearly how to work with the data, and why it is necessary. And, I learned something new.

        Thanks again for the "finger pointing at the Moon".

Re: eq evaluates a variable as equal to two different strings
by BrowserUk (Patriarch) on Jan 30, 2015 at 20:56 UTC

    Can't reproduce your results. Your code is incomplete (no population of %info or $key), so I had to mock up that bit:

    $key = 'fred'; $info{$key} = 'false'; $baz = $info{$key}; printf "[%s] [%s] [%d] [%d] [%d]\n", $baz, unpack('H*', $baz), $baz eq 'true', $baz eq 'false', $baz eq 'default';; [false] [66616c7365] [0] [1] [0]

    Looks like you should post a complete, runnable example that reproduces your problem.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
    In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked

      Thanks for taking a look. I did note (see my 2nd sentence of my original post) that I, also, cannot reproduce the problem. It's only occurring in situ. So, it's more a question of whether or not anyone has run into the same or similar issue, and what they discovered about it.

      I'm also happy to provide the original program where the problem is occurring, but at 20k it seemed a bit long to post unsolicited; also, there are external conditions for running it, such as interacting with a active AWS/EC2 account. But anyone as curious about this as I am can just ask, and I'll share the full program where the problem manifests.