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

I am probably reinventing the wheel here but I am attempting to correct a problem i glossed over earlier. I am basically making a call to a sub in another file that I have included using require. When i run it I get the error shown below.

Basically $request_hash is a hash of headers for use with mechanize and sometimes the request requires special handling (date updated and appended, particular cookie added, servers changed, etc.) so it needs to call a function in a another file. The function name is added to the headers as Logic: function_name. This is done manually and the function is added to the request_logic.pl. I am trying to figure out what I am doing wrong. I have used no strict "refs" here, the code works fine that way, and that is wrong. The code works great though, i just want the correct syntax. Any input, ideas, or help would be appreciated.

As a note nnnnn exists as a test function in request_logic.pl. I did not post the whole thing because its about 700 lines now. subs::dbg is the logging function i use.

thanks.

p.s. this is my first posted question, so please forgive me for any formatting mistakes in it. but perlmonks has been an awesome resource. thanks again.

if ($request_hash{Logic}) { no strict "refs"; subs::dbg($log_file, 0, "<$script_file> This is the Logic: $requ +est_hash{Logic} \n\n"); $function_name = "request_logic::".$request_hash{Logic}; + eval{$returned_hash_ref = &$function_name($request_hash_ref, $lo +g_file)}; #should call any set function name if ($@) { subs::dbg($log_file, 0, "<$script_file> Error from eval: $@"); #i +f there is an eval error } else { subs::dbg($log_file, 0, "<$script_file> Hash returned from +moodification from function $function_name"); subs::dbg($log_file, 0, Dumper $returned_hash_ref); } delete($request_hash{Logic}); #delete the ha +sh value with the logic in it }
This is the error.
201017 05:28 - <test_check.script> Error from eval: Can't use string ( +"request_l ogic::nnnnn") as a subroutine ref while "strict refs" in use at web_ac +torv.0755. pl line 282, <ACT> line 55.

Replies are listed 'Best First'.
Re: use strict refs unless you can't figure out the syntax
by GrandFather (Saint) on Jan 07, 2010 at 11:36 UTC

    Looks like you may be trying to dispatch to a selected sub by storing the name of the sub in a hash. If you store a reference to the sub instead the intent becomes clearer, to need for the string ref is removed, maintenance becomes easier and the code is better checked for typos. Consider (sample code only - unchecked):

    my %request_hash = ( my $returned_hash_ref = Logic => \&request_logic::nnnnn, ); #... if ($request_hash{Logic}) { $request_hash{Logic}->($request_hash_ref, $log_file); } else { #...

    True laziness is hard work

      I must admit I'm confused by the intent of theleftsock (who seems to have chosen a very complicated way to do a fairly simple thing), but I'm also confused by the intent of the extra lexical scalar  $returned_hash_ref present in your reply. What does this give you (other than another maintenance worry) that you do not get from the hash and key you already have in hand?

      >perl -wMstrict -le "sub S { print 'hi ', $_[0] } sub T { print 'lo ', $_[0] } sub U { print '-- ', $_[0] } my %hash = ( my $x = L => \&S, my $y = M => \&T, my $z = N => \&U, ); print $x; $hash{$x}->($x); $hash{L} ->('L'); $hash{$_}->($_) for qw(L M N); " L hi L hi L hi L lo M -- N

        thank you for the response. How would you do this same thing if you didn't know what the function name was to create a hard reference, the subs exist in a separate file, and you didn't know if the function even existed? (so you have to handle the error, if it hasn't been added yet or it doesn't work correctly) Unfortunately due to my inexperience, I am forced append the file name to the beginning to make a call like.

        $function_name = "request_logic::".$request_hash{Logic};

        Is there better way is really my question? I am uncertain how to create the reference to this sub and keep the program from dying if it throws some strange error. The $returned_hash_ref is because the sub that gets called alters the original request and I want to make sure the alterations get compared to the original. It might be an obtuse way to do it though, let me think about it...

        thank you very much for you responses.

        A misguided "copy/paste/misguided edit" sequence (covered by the parenthesised escape clause maybe?) :-(.


        True laziness is hard work
Re: use strict refs unless you can't figure out the syntax
by JavaFan (Canon) on Jan 07, 2010 at 11:05 UTC
    I have used no strict "refs" here, the code works fine that way, and that is wrong. The code works great though, i just want the correct syntax.
    You seem to have the impression use strict forbids incorrect syntax. It doesn't. If the syntax isn't correct, the compiler will barf. strict will prevent you from using certain syntactically correct constructs.

    Your snippit doesn't give me enough context to determine whether there's a good solution that avoids using strings as function names. (You could use the PACKAGE->$function_name syntax, and shift off the first argument in the function, but that doesn't buy you anything - it will still come with all the drawbacks of &$function_name).

Re: use strict refs unless you can't figure out the syntax
by BrowserUk (Patriarch) on Jan 08, 2010 at 07:13 UTC

    Why not put the fully qualified function name into the hash?

    $request_hash{Logic} = 'request_logic::funcname';

    Then invoking the function becomes:

    eval { &{ $request_hash{Logic} }( $request_hash_ref, $log_file ); }; if( $@ ) { ...

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.