Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Referencing a hash of hashes

by Ronnie (Scribe)
on Aug 18, 2006 at 12:54 UTC ( #568128=perlquestion: print w/replies, xml ) Need Help??

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

Hello Monks after yesterdays foolish question - well the question wasn't foolish it was the dolt asking!! - I've a slightly more complex poser. I've a list of subroutines that are to run as part of a daily script. If one of them fails we want to automate the re-running of this script without editing it. I've got the mechanism for doing this unfortunately I can't get any of the subroutines to execute! The subroutine names are held in a hash table :-
my %scripts = ( "010" => { sub => "ACC_GET_STEP", step => '010', }, "020" => { sub => "ACC_PUT_STEP", step => '020', }, "030" => { sub => "ACC_GET_STEP", step => '030', }, );

(The above is a cut down version of the hash values as there are also anonymous entries for the parameters required set up at run time). Now I know that part of the problem is being caused because I'm using the strict pragma. I know how to create a reference to a hash table but an entry to a hash within the hash table?
Can't use string ("ACC_PUT_STEP") as a subroutine ref while "strict re +fs" in use at xxrc_test_putstep.pl line 211.
However even if I remove the strict pragma this code still fails.
SCRIPT: for $script (sort keys %scripts) { next SCRIPT if ! defined $scripts{$script} {execute} ; $step = $scripts{$script} {step} ; $sub = $scripts{$script} {sub} ; if ($script == '020') { print "\n\tRunning Step :: $step Sub :: $sub\n" ; $result = system(&$sub($file, $step)) ; if ($result) { print "\n\tFailed!\n" ; } else { print "\n\tSucceeded!\n" ; } } }

I can think of some alternative - long long winded - ways of re-writing this without using a hash table at all but would like my code to be more concise. Any suggestions?

Replies are listed 'Best First'.
Re: Referencing a hash of hashes
by Limbic~Region (Chancellor) on Aug 18, 2006 at 13:01 UTC
      Thanks, I've now read it and book marked it for future - no pun intended - reference. Cheers, Ronnie
Re: Referencing a hash of hashes
by imp (Priest) on Aug 18, 2006 at 13:03 UTC
    This is because you are storing the name of the subroutine in your hash, when you should be storing a reference to the subroutine.
    my %scripts = ( "010" => { sub => \&ACC_GET_STEP, step => '010', }, "020" => { sub => \&ACC_PUT_STEP, step => '020', }, "030" => { sub => \&ACC_GET_STEP, step => '030', }, );
    You can then call the sub like this:
    $sub = $scripts{$script}{sub} ; $sub->($file, $step); # Or &$sub($file, $step);
    The first way of doing it looks cleaner and and running subs with a & prefix is a bad habit as it has magic when no arguments are passed.
      Thanks I've implemented your suggestion and am using the tidy -> version. Can I be a pest and ask one further question? (Okay it's really 2 if you count the request!) For audit trail purposes the line -
      print "\n\tRunning Step :: $step Sub :: $sub\n" ;

      is to be written to a log file for each subroutine run. The $sub value is a reference to a subroutine and I've tried various ways to dereference this into plain text without success - I could be even more tedious and add an entry to the hash that is just text holding the subroutines name. I've been reading pages 251 onwards in Programming Perl and I've had plenty of messages :-
      <***** xxrc_test_step_subs S T A R T S *****> Not a SCALAR reference at xxrc_test_putstep.pl line 206. rcruickshank@heather$ xxrc_test_putstep.pl <***** xxrc_test_step_subs S T A R T S *****> Not a HASH reference at xxrc_test_putstep.pl line 206.

      but no success! I thought it was something to do with a coderef but I've not yet found an example that works. Sorry to have be a pest.
      Cheers
      Ronnie
        You can get this information from B::Deparse.
        sub a { print "foo\n"; } use B::Deparse; my $deparser = B::Deparse->new('-p'); print $deparser->coderef2text(\&a);
        Update - You can get the source of the subroutine with B::Deparse I should have said. Perhaps you meant the name of the subroutine.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://568128]
Approved by Limbic~Region
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (7)
As of 2019-10-14 22:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?