Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Using FreezeThaw correctly?

by Rhys (Pilgrim)
on Sep 21, 2004 at 00:06 UTC ( [id://392534]=perlquestion: print w/replies, xml ) Need Help??

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

ALTS, monks!

I'm having a little problem using FreezeThaw to compare two hashes. The hashes are fairly complex (hash of lists of hashes). According to perlfaq4, I ought to be able to do this in a test file:

use FreezeThaw qw(cmpStrHard); use JScan::ReadCrossLinks; use Test::More; BEGIN { plan tests => 1, todo => [1] }; # Initialize %crosslinkscorrect with what we expect. ################################################## # Test 1. Read our test file and compare to the control. ReadCrossLinks(\%crosslinks, \%options); # This should fail if the hashes are different, right? ok(cmpStrHard(\%crosslinks, \%crosslinkscorrect));

So the problem is that this test always succeeds, even when I feed it mangled data. What gives? Alternatively, is there another, simpler way to compare the contents of two hashes that contain complex data like this?

--J

Replies are listed 'Best First'.
Re: Using FreezeThaw correctly?
by PodMaster (Abbot) on Sep 21, 2004 at 00:21 UTC
    Your code snippet doesn't demonstrate what you claim. What gives?
    Alternatively, is there another, simpler way to compare the contents of two hashes that contain complex data like this?
    How can it possibly get any simpler?
    use FreezeThaw qw[cmpStrHard]; use strict; use warnings; my @one = ( 1 .. 10, ( [ 1 .. 2] ) x 5 ); my @two = ( 12 .. 21, ( [ 11 .. 22] ) x 4 ); warn "one one ", cmpStrHard(\@one,\@one) == 0 ? "same\n" : "different\ +n"; die "one two ", cmpStrHard(\@one,\@two)== 0 ? "same\n" : "different\n" +; __END__ one one same one two different
    update: Like my snippet (and perlfaq4) demonstrate is that cmpStrHard returns 1 when the data structures are different, not when they are identical.

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

      All I did was ask a simple question after RTFM, and after trying several different things, and after using SuperSearch. I'm not an idiot, nor am I lazy.

      BUT, to humor you, from perlfaq4:

      use FreezeThaw qw(cmpStr cmpStrHard); %a = %b = ( "this" => "that", "extra" => [ "more", "stuff" ] ); $a{EXTRA} = \%b; $b{EXTRA} = \%a; printf "a and b contain %s hashes\n", cmpStr(\%a, \%b) == 0 ? "the same" : "different"; printf "a and b contain %s hashes\n", cmpStrHard(\%a, \%b) == 0 ? "the same" : "different"; The first reports that both those the hashes contain the same data, while the second reports that they do not. Which you prefer is left as an exercise to the reader.

      So yeah, it ought to be really simple. But if that is the case, shouldn't I be able to make the test fail when the two hashes are different?

      Another thing I'm curious about: I mentioned that the test unexpectedly succeeded. There really isn't anything interesting when that happens. What information should I have provided?

      In any event, I've actually tracked down the problem. There were two:

      1. Despite the verbage in perlfaq4, cmpStr and cmpStrHard return the same thing on success/failure. I'm not sure what the difference is supposed to be between these two functions.
      2. I was not actually setting the two hashes to be equal, so my results never changed because the test was always 'failing'. So even when I thought I was inverting the behavior, I wasn't. Also, I'm going to have to use is() instead of ok() since I expect 0. Data::Dumper++ for helping me find the bug in the actual code being tested. (Which, I suppose, was the original point.)

      So PodMaster-- for posting and not actually helping. All I needed was confirmation that I was using FreezeThaw correctly. Too bad you couldn't do that, or at least keep silent.

      Anyway, here's the only thing I had to change to the original code. Instead of the ok() line I used:

      is( cmpStrHard(\%crosslinks, \%crosslinkscorrect), '0', "cmpStrHard" );

      So the test now does the right thing. Now I just have to make sure ReadCrossLinks() does the right thing...

      --J

      Update: Added working version of the code to the bottom of this reply node.

      Update 2: The confusion for me was in the text from perlfaq4 that says The first reports that both those the hashes contain the same data, while the second reports that they do not. This let me to believe that cmpStr was not cmpStrHard, and that perhaps there was a typo in the code example. Only after I understood what the two functions do did the phrase make sense.

      But that's backwards. The docs are supposed to help me understand the functions, not prove my understanding after the fact. FreezeThaw wasn't any better, since it's highly geared toward OO programming (of which I admit to knowing little).

      I think the text in perlfaq4 would read better as:

      The first reports that the hashes %a and %b shown contain the same data, while the second reports that they are different, since $a{EXTRA} and $b{EXTRA} point to the same data, but are not equal to each other.

      (This assumes that I know what I'm talking about, of course, but I think that's correct.) A little wordier, but much clearer, IMvHO.

        All I did was ask a simple question after RTFM, and after trying several different things, and after using SuperSearch. I'm not an idiot, nor am I lazy.
        All I did was answer the question (using your own words no less) without calling you an idiot or lazy. I can't help if you feel like an idiot.
        So yeah, it ought to be really simple. But if that is the case, shouldn't I be able to make the test fail when the two hashes are different?
        But it is simple, and you can make the test fail, you just have to write it correctly. I thought that would be obvious once you understood how cmpStrHard works. ok( not cmpStrHard(\%crosslinks, \%crosslinkscorrect) );
        Another thing I'm curious about: I mentioned that the test unexpectedly succeeded. There really isn't anything interesting when that happens. What information should I have provided?
        Something everyone can run that demonstrates your dilemma. Only you have access to JScan::ReadCrossLinks , ReadCrossLinks, \%crosslinks, \%options...
        So PodMaster-- for posting and not actually helping. All I needed was confirmation that I was using FreezeThaw correctly. Too bad you couldn't do that, or at least keep silent.
        I know I helped ( I showed you that you're not using FreezeThaw correctly). I wasn't very explicit and verbose, but i thought it was obvious. Too bad you didn't get it.

        MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
        I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
        ** The third rule of perl club is a statement of fact: pod is sexy.

Re: Using FreezeThaw correctly?
by Rhys (Pilgrim) on Sep 21, 2004 at 14:31 UTC
    I also found another way to do this without using FreezeThaw. Test::More also includes a function is_deeply that works about the same way:

    is_deeply( \%crosslinks, \%crosslinkscorrect, "hash_comparison" );

    This also much better for using in test scripts, since it returns more information when the test fails:

    t/ReadCrossLinks....NOK 1# Failed test (t/ReadCrossLinks.t at line + 32) # Structures begin differing at: # $got->{10.5.5.1}[0] = undef # $expected->{10.5.5.1}[0] = Does not exist # Looks like you failed 1 tests of 1.

    Not to mention the fact that since my app doesn't use FreezeThaw for anything else, I can remove that dependency from Makefile.PL. :-)

    NOTE: The structures I will be comparing contain only scalars and anonymous refs. I have not tried is_deeply with refs as shown in perlfaq4, so I don't know if it acts more like cmpStr or cmpStrHard, but it works wonderfully for my purpose.

    --J

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://392534]
Approved by sintadil
Front-paged by Courage
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (3)
As of 2024-04-20 15:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found