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

hi, i'm using a hash which i declare in the beginning of the program
and i have a dozen subroutines within which i assign various key::value pairs to the hash. i thought variables were global in scope by default, unless specifically declared as local or "my" variables, but if i try to access any value of the hash from outside those subroutines, i get no data at all. Could u please suggest something ?i have a killer deadline to meet. thanks

Replies are listed 'Best First'.
RE: make a hash globally accessible
by Russ (Deacon) on Oct 06, 2000 at 05:43 UTC
    When you say, "assign key::value pairs to the hash" do you mean like this:
    sub func{ $Hash{Key} = 'Value'; }
    or do you mean:
    sub func{ %Hash = ('Key', 'Value'); }
    If the second, then you are overwriting your hash each time.

    More information and some sample code would go a long way, here.

    Russ
    Brainbench 'Most Valuable Professional' for Perl

(Ovid) Re: make a hash globally accessible
by Ovid (Cardinal) on Oct 06, 2000 at 05:47 UTC
    It would help if you post a bit of code so we can see what's going on. You are correct that a hash declared globally should retain its data throughout the program, but there are various ways one could subvert this. Perhaps you have redefined the hash within subs? Maybe you're not really assigning to the hash keys? Are you using conditionals that fail without warning? Is your hash being populated through files that aren't being opened, but you don't know that because you didn't check for a successful open? The possibilities are endless.

    First, make sure that you are using the -w switch at the beginning of your program, that might catch a few things. Also, use strict;.

    The only sure advice I can give you is to learn to use the perl debugger. Then, if your hash is named %somehash, when you get to an area of the program where the hash should be populated, you can type x %somehash to have a nicely formatted print of the hash contents, if any.

    If you do post some code, be sure to wrap the code in <CODE></CODE> tags so it will be properly formatted.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just go the the link and check out our stats.

RE: make a hash globally accessible
by acid06 (Friar) on Oct 06, 2000 at 05:48 UTC
    First of all, it looks like you're not useing strict. Always use strict.
    Then if you're following this advice and using use strict you need to declare all the hashes, arrays, whatever that you want to be acessed globally, outside the subroutines, and those you don't want to be globally acessed, declare them inside the subroutines.
Re: make a hash globally accessible
by vipinh (Novice) on Oct 06, 2000 at 20:39 UTC
    i am using use vars qw(%seg000) - where %seg000 is the hash name
    here is a snippet of code :<br> use vars qw(%seg000); %seg000 = (); #ONE OF THE MANY SUBROUTINES WHERE THE HASH IS ASSIGNED VAUES sub ProcessSegment000 { my $dataline = shift; $seg000{fileid} = substr($dataline,0,3); print "INSIDE the segment : " . $seg000{fileid} . "\n"; -#THIS PRINT + STATEMENT SHOWS THAT THE HASH NOW CONTAINS DATA $seg000{filetype} = substr($dataline,3,3); $seg000{fileversionid} = substr($dataline,6,5); $seg000{impactionind} = substr($dataline,11,1); $seg000{expactionind} = substr($dataline,12,1); $seg000{mornetcaseid} = substr($dataline,13,30); } sub readfile -- THIS SUB FIRES THE ABOVE SUBROUTINE { my $myfile = shift; while (!eof $myfile){ chomp($input = readline($myfile)); my $segmentno = substr($input,0,3); eval "\%seg000 = &ProcessSegment$segmentno(\$input,\\\%seg000) +"; print "OUTISDE THE SUBROUTINE " . $seg000{fileid}; #THIS PRINT STATEMENT SHOWS NO DATA IN THE HASH. } } $file="c\:\\0008022.fnm"; -the data file to be read open FILEHANDLE, "<$file"; readfile(\*FILEHANDLE);
      I do not like that eval. I would rather use a hash of subroutine references or a wrapper subroutine taking the segment value or a closure scheme.

      That said, you're very close. Assigning the results of the ProcessSegmentxxx call to %seg000 would work -- if you actually returned the hash from the subroutine. Likewise, passing a reference to the hash would work -- if you actually used the reference in the subroutine to hold data.

      The code to do that would be similar to:

      sub ProcessSegment000 { my $dataline = shift; my $seg000 = shift; $seg000->{fileid} = substr($dataline,0,3); # et cetera
      Note the dereferencing arrow.

      Seriously though, I shudder to think at the kind of work you mihgt have to do to update all of those similar subs. That'll be the next thing to tackle, right?