Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Dereferencing %hash that does not exist.

by perldarren (Novice)
on Sep 04, 2013 at 10:09 UTC ( #1052277=perlquestion: print w/ replies, xml ) Need Help??
perldarren has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'm having some trouble and would appreciate some advice.

I have a couple of scripts that reference the same perl module.
In some of the scripts I want to pass a dispatch table to the module and in others I do not, where I do, I pass:
my %modifier = ( reverse_modifier => \&reverse_modifier ); my $return = my::module::exit_routine(\%modifier);
Where I don't I WANT to pass:
my $return = my::module::exit_routine();
In the module exit_routine dereferences %modifier like this:
my %revmod = %{$_[0]};
The scripts that do not pass %modifier result in:
Can't use an undefined value as a HASH reference at /usr/local/lib/perl5/site_perl/5.10.1/...

Whilst those that do pass %modifier work as expected.

My question is - How can I make this work for both scenarios? Preferably I would like to modify the module so that it can deal with the 2 scenarios and save me from modifying all of the scripts that use it.

Many thanks for your time and patience.

Regards,
Darren

Comment on Dereferencing %hash that does not exist.
Select or Download Code
Re: Dereferencing %hash that does not exist. (conditional)
by Anonymous Monk on Sep 04, 2013 at 10:13 UTC
    :D perlintro#if
    my( $ref ) = @_; my %revmod; if( ref $ref ){ %revmod = %$ref; } ...

    Or  my %revmod = eval { %{ $_[0] } };

      Cool problem solved, thanks very much

      Never fails to amaze me how I sometimes just seem to have no grasp on something so fundamental :(

      I keep on trying though !

      Regards,
      Darren
        Ok, so I implemented the eval variant of this and it seems to work well, thank you guys.
        I now have a slightly different issue.

        my::module::exit_routine is also passed into a simple logging module that I put together like this:
        my $log = LogSimple->new(logdir => $logdir, logfile => $logfile, exit +=> \&my::module::exit_routine )
        In this particular script whenever my::module::exit_routine is called I need to pass the %modifier dispatch table so I need to setup the $log object like this:
        my $log = LogSimple->new(logdir => $logdir, logfile => $logfile, exit +=> \&my::module::exit_routine(\%modifier) )
        Except this does not work, the error is:
        Not a CODE reference at /usr/local/lib/perl5/site_perl/5.10.1/LogSimple.pm

        I have to admit that my OOP is really in it's infancy.

        Really not sure on this one so any help much appreciated.

        Cheers, Darren
Re: Dereferencing %hash that does not exist.
by choroba (Canon) on Sep 04, 2013 at 10:28 UTC
    In recent Perl (which 5.10.1 is in this context), you can also use the defined-or operator:
    my $revmod = %{ $_[0] // {} };

    Update: It should work with plain ||, too, in the older versions. Just make sure you never call it with 0 as the argument.

    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Dereferencing %hash that does not exist.
by perldarren (Novice) on Sep 04, 2013 at 20:31 UTC
    Thought I ought to make this thread a little clearer - I thought my problem was gone but it seems that it's only just started:
    From my script I can do these ok:
    
    my $return = my::module::exit_routine(); sub reverse_modifier { # I modify default behaviour of the exit routine if I get passed - som +e times I am not needed. } my %modifier = ( reverse_modifier => \&reverse_modifier ); my $return = my::module::exit_routine(\%modifier);
    In my::module::exit_routine I can deal with %modifier being present or not:
    
    my %revmod = eval { %{ $_[0] } }
    But here is my new sticking point - I am unable to find a way to do this from my script:
    
    my $log = LogSimple->new(_exit => my::module::exit_routine(\%modifier) + ); $log->err("An error occured, _exit will happen before I exit but now I + want to force exit_routine to also use the \%modifier as well")
    When an error is trapped and $log->err is executed I get:
    Not a CODE reference at /usr/local/lib/.../LogSimple.pm line 122:
    From my LogSimple package line 122 = $exit_ref->($self);
    
    
    Effectively I am trying to send a reference which has another reference as one of it's parameters and my syntax is completely jiggered.
    Infact, the whole concept could be busted up now that I am trying to introduce %modifier to plug up a hole I never knew I had.
    
    Package LogSimple ... sub wlog { my ($self,$MESSAGE,$ERR,$LEVEL,$LOGLEVEL) = @_; my $TIME = datetime(); my $exit_ref; if ( $LOGLEVEL <= $self->{_loglevel} ) { open (LOG, ">>$self->{_log}") || warn "Unable to open log file + $self->{_log}: $!"; print LOG "$LEVEL: $TIME : $self->{_script} : $MESSAGE\n"; print "$LEVEL: $TIME : $self->{_script} : $MESSAGE\n" if ( $se +lf->{_verbosity} > 0 ); close (LOG); } if ( $ERR ) { if ( exists $self->{_exit} ) { use Data::Dumper; print Dumper $self->{_exit}; $exit_ref = $self->{_exit}; $exit_ref->($self); # LINE 122 if ( $LOGLEVEL <= $self->{_loglevel} ) { open (LOG, ">>$self->{_log}") || warn "Unable to open log file + $self->{_log}: $!"; print LOG "$LEVEL: $TIME : $self->{_script} : $MESSAGE\n"; print "$LEVEL: $TIME : $self->{_script} : $MESSAGE\n" if ( $se +lf->{_verbosity} > 0 ); close (LOG); }; } exit $ERR } }
    Any assistance much appreciated.
    
    Regards,
    Darren

      The Dumper output from line 120 should make it clear what $exit_ref will be set to but the error message makes it clear that it is not a code reference. My guess is that my::module::exit_routine(\%modifier) doesn't return a code reference, though it is only a guess as much of your code is not presented.

        Hello.
        Dumper output $VAR1 = \'';
        
        If I remove %modifier and send exit => \&Hitachi::Raidcom::exit_routine there's a whole bunch of $VARS but if I try to add the argument as in this snippet, it breaks.
        
        Here is the reverse modifier sub and the dispatch table:
        
        sub reverse_modifier { my (@undo) = @{$_[0]}; my @rdis; my @rdel; my @newundo; for my $cmd (@undo) { if ( $cmd =~ /lock/ ) { push(@newundo, $cmd) } if ( $cmd =~ /disconnect/ ) { push (@rdis, $cmd) } if ( $cmd =~ /delete/ ) { push (@rdel, $cmd) } if ( $cmd =~ /unlock/ ) { push(@newundo,(@rdis,"sleep +22",@rdel,$cmd)) } } return @newundo; } my %modifier = ( reverse_modifier => \&reverse_modifier ); # Setup the log object my $log = LogSimple->new( logdir => $logdir, logfile => $logfile, logl +evel => $loglevel, verbosity => $verbosity, exit => \&Hitachi::Raidco +m::exit_routine(\%modifier) );
        This is the entire LogSimple module:
        package LogSimple; use strict; use Time::Format qw(%time %strftime %manip); use Exporter; use vars qw($VERSION @ISA @EXPORT); our @ISA = qw(Exporter); # Items to export into callers namespace by default. Note: do not expo +rt # names by default without a very good reason. Use EXPORT_OK instead. # Do not simply export all your public functions/methods/constants. # This allows declaration use LogSimple ':all'; # If you do not need this, moving things directly into @EXPORT or @EXP +ORT_OK # will save memory. our %EXPORT_TAGS = ( 'all' => [ qw( ) ] ); our @EXPORT_OK = ( ); our @EXPORT = qw( ); our $VERSION = '0.01'; # Preloaded methods go here. sub new { my $class = shift; my %options = @_; my $self = { _logdir => 'LogDEC_Dir', _logfile => 'logfile.log', _loglevel => '5', _verbosity => '1', _script => $0, }; if ( exists $options{'logdir'} ) { $options{'logdir'} =~ s/\///g; $self->{_logdir} = $options{'logdir'} } else { # user didn't specify logdir, tell them where the default was +created print "Default log directory: $self->{_logdir} - change it to +not see this message\n"; } if ( exists $options{'logfile'} ) { $self->{_logfile} = $options{' +logfile'} }; if ( exists $options{'loglevel'} ) { $self->{_loglevel} = $options +{'loglevel'} }; if ( exists $options{'verbosity'} ) { $self->{_verbosity} = $optio +ns{'verbosity'} }; if ( exists $options{'exit'} ) { $self->{_exit} = $options{'exit'} + }; $self->{_log} = "$self->{_logdir}/$self->{_logfile}"; unless ( -w $self->{_logdir} ) { mkdir ( $self->{_logdir}, 0700 ) || die "Unable to create log +directory $self->{_logdir}: $!"; }; bless $self, $class; return $self; } sub datetime { return $time{'dd-mm-yyyy_hh.mm.ss'} } sub inf { my ($self,$MESSAGE) = @_; my @PASS; push(@PASS,@_); push(@PASS,("","INF", 3)); wlog(@PASS); } sub wrn { my ($self,$MESSAGE) = @_; my @PASS; push(@PASS,@_); push(@PASS,("","WRN", 2)); wlog(@PASS); } sub dbg { my ($self,$MESSAGE) = @_; my @PASS; push(@PASS,@_); push(@PASS,("","DBG", 4)); wlog(@PASS); } sub raw { my ($self,$MESSAGE) = @_; my @PASS; push(@PASS,@_); push(@PASS,("","RAW", 5)); wlog(@PASS); } sub err { my ($self,$MESSAGE,$ERR) = @_; my @PASS; push(@PASS,@_); push(@PASS,("ERR", 1)); wlog(@PASS); } sub wlog { my ($self,$MESSAGE,$ERR,$LEVEL,$LOGLEVEL) = @_; my $TIME = datetime(); my $exit_ref; if ( $LOGLEVEL <= $self->{_loglevel} ) { open (LOG, ">>$self->{_log}") || warn "Unable to open log file + $self->{_log}: $!"; print LOG "$LEVEL: $TIME : $self->{_script} : $MESSAGE\n"; print "$LEVEL: $TIME : $self->{_script} : $MESSAGE\n" if ( $se +lf->{_verbosity} > 0 ); close (LOG); } if ( $ERR ) { if ( exists $self->{_exit} ) { use Data::Dumper; print Dumper $self->{_exit}; $exit_ref = $self->{_exit}; $exit_ref->($self); if ( $LOGLEVEL <= $self->{_loglevel} ) { open (LOG, ">>$self->{_log}") || warn "Unable to open log file + $self->{_log}: $!"; print LOG "$LEVEL: $TIME : $self->{_script} : $MESSAGE\n"; print "$LEVEL: $TIME : $self->{_script} : $MESSAGE\n" if ( $se +lf->{_verbosity} > 0 ); close (LOG); }; } exit $ERR } } 1;

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (15)
As of 2015-07-01 15:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (6 votes), past polls