http://qs1969.pair.com?node_id=521757

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

I am attempting to read a flat file that describes an array of hash references into a similar DBM hash where it will be modified and stored for another process. When I test this by first printing out the hash_ptr everything works!When I print out hash_ref( with same address) it references nothing?
The flat file has this
@HASHES = ( \%Data_Directories_fetch, \%DataDirectories_erase, \%Progr +am_fetch, \%Program_erase, \%Configuration_and_Table_Files_erase, \%Configuration_and +_Table_Files_fetch, \%Create_Database, \%Load_Database );
The function is called with no arguments.
Thanks Much!


sub loadDefaultsToDBM { my $cntr = 0; foreach $element (@HASHES) { print "$cntr --$element "; switch($cntr++) { case 0 { print "Data_Directories_fetch\n"; $TESS_CONFG{"Data_D +irectories_fetch"} = $element; } case 1 { print "Data_Directories_erase\n"; $TESS_CONFG{"Da +ta_Directories_fetch"} = $element; } case 2 { print "Program_fetch\n"; $TESS_CONFG{"Pr +ogram_fetch"} = $element; } case 3 { print "Program_erase\n"; $TESS_CONFG{"Pr +ogram_erase"} = $element; } case 4 { print "Configuration_and_Table_Files_erase\n"; $T +ESS_CONFG{"Configuration_and_Table_Files_erase"} = $element; } case 5 { print "Configuration_and_Table_Files_fetch\n"; $T +ESS_CONFG{"Configuration_and_Table_Files_fetch"} = $element; } case 6 { print "Create_Database\n"; $TESS_CONFG{"Cr +eate_Datebase"} = $element; } case 7 { print "Load_Database\n"; $TESS_CONFG{"Lo +ad_Datebase"} = $element; } } } ### Test it! my $hash_ptr = \%Program_fetch; print "$hash_ptr\n"; while ( ($key, $value) = each %{$hash_ptr} ) { print "$key => $value\n"; } my $hash_ref = $TESS_CONFG{"Program_fetch"}; print "Result: $hash_ +ref\n"; my @keys = keys %$hash_ptr; while ( ($key, $value) = each %{$hash_ref} ) { print "$key => $value\n"; } }

Replies are listed 'Best First'.
Re: Dereferencing Mystery
by tirwhan (Abbot) on Jan 07, 2006 at 23:13 UTC
    1. You shouldn't use Switch.pm, it has subtle bugs.
    2. What's the switch for here anway, all you're doing is execute one "case" after the other, there's no fall-through or anything that requires this execution out of a standard for-loop.
    3. Running this codes gives the following output:
    0 --HASH(0x82bfd04) Data_Directories_fetch 1 --HASH(0x828b9a8) Data_Directories_erase 2 --HASH(0x82bbf40) Program_fetch 3 --HASH(0x82bfcbc) Program_erase 4 --HASH(0x82bbec8) Configuration_and_Table_Files_erase 5 --HASH(0x815b734) Configuration_and_Table_Files_fetch 6 --HASH(0x82bbee0) Create_Database 7 --HASH(0x82bbe38) Load_Database HASH(0x82bbf40) Result: HASH(0x82bbf40)

    Loading some values into the Program_fetch hash first gives:

    0 --HASH(0x82bc21c) Data_Directories_fetch 1 --HASH(0x82bfd00) Data_Directories_erase 2 --HASH(0x8160c8c) Program_fetch 3 --HASH(0x82bc0f0) Program_erase 4 --HASH(0x82bfce8) Configuration_and_Table_Files_erase 5 --HASH(0x815b728) Configuration_and_Table_Files_fetch 6 --HASH(0x82bc12c) Create_Database 7 --HASH(0x82bfd84) Load_Database HASH(0x8160c8c) 1 => 2 3 => 4 Result: HASH(0x8160c8c) 1 => 2 3 => 4

    Which is exactly what I'd expect. What are you expecting to see?


    There are ten types of people: those that understand binary and those that don't.
      My second hash reference points to the same address as the first but, unlike yours, doesn't print out the values. The second is a DBM record on the drive.

      So, I think it's not resolved?
      The switch is just a way to associate the hash addresses with a descriptive string. Perhaps not the bast way but the mystery is that I get the following.
      The loops are referencing the same hash but what I can't explain is why only the first loop works?

      0 --HASH(0x18b73bc) Data_Directories_fetch 1 --HASH(0x18a50f0) Data_Directories_erase 2 --HASH(0x18b7518) Program_fetch 3 --HASH(0x18b74e8) Program_erase 4 --HASH(0x555250) Configuration_and_Table_Files_erase 5 --HASH(0x555280) Configuration_and_Table_Files_fetch 6 --HASH(0x18b8224) Create_Database 7 --HASH(0x18b8254) Load_Database HASH(0x18b7518) /reba/shlib => Y /airreba/procs => Y /xcape/bin => Y /reba/bin => Y /airreba/tables => Y /reba/onetime => Y /xcape/bin_util => Y /reba/perlib => Y Result: HASH(0x18b7518)

      Edit: g0n - code tags

      Ok! That seems to explaint it!!! Gee I fool feelish! Thanks Much!
Re: Dereferencing Mystery
by planetscape (Chancellor) on Jan 08, 2006 at 01:10 UTC
Re: Dereferencing Mystery
by graff (Chancellor) on Jan 08, 2006 at 00:39 UTC
    Your use of the term "flat file" does not make sense to me. I can't figure out what you really mean when you say:
    The flat file has this
    @HASHES = ( \%Data_Directories_fetch, \%DataDirectories_erase, \%Program_fetch, \%Program_erase, \%Configuration_and_Table_Files_erase, \%Configuration_and_Table_Files_fetch, \%Create_Database, \%Load_Database );
    That's just a snippet of perl code, building an array from a list of references to hashes. It is not a "flat file", because a flat file is a stream of plain-text data, usually structured as a table (each line of text is a row, containing one or more columns).

    When you say "I am attempting to read a flat file that describes an array of hash references...", I don't understand how a flat file can do this -- hash references can only exist as such in a running perl script. A flat file can contain the data that would be loaded into a hash by a perl script, and then you can use a reference to the hash within that script. But the flat file has nothing to do directly with hash references.

    You'll need to clarify what it is you are trying to do.

      Flat file isn't correct! The file is actually a listing of mostly hashes with default values to be used by a menu. The user of the menu makes some changes in the selections and it's these changes I want to save to disk for another process to read.

      %Program fetch for example

      %Program_fetch = ( "/airreba/procs" => "Y", "/reba/bin" => "Y", "/reba/onetime" => "Y", "/reba/perlib" => "Y", "/reba/shlib" => "Y", "/xcape/bin" => "Y", "/xcape/bin_util" => "Y", "/airreba/tables" => "Y", );

      Edit: g0n - code tags

        general comment: If the only choices are on & off ("Y" & something else), use "boolean" values instead -- it will make things a lot easier and cleaner cause you'll avoid code like if($foo eq 'Y') (or worry about case).. use 1 (or another non-zero number) for true and 0/undef for false. Then you can just do if($foo). (Depending on the usage you could just do if(exists $someHash{someKey}) as well ..). A good reference is True or False? A Quick Reference Guide
Re: Dereferencing Mystery
by davidrw (Prior) on Jan 08, 2006 at 01:06 UTC
    ditto on the above two comments, especially re: 'flat file' ..
    also wanted to add that, as far as i can tell, your foreach/switch loop could be replaced with simply a hash slice assignment:
    @TESS_CONFIG{ qw/ Data_Directories_fetch Data_Directories_erase Program_fetch Program_erase Configuration_and_Table_Files_erase Configuration_and_Table_Files_fetch Create_Database Load_Database / } = @HASHES;
      Thanks, I'll use the hash slice.