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

I am writing a program that uses an XML control card. I've allowed users to define exceptions within the XML. For instance:
<exception> <error>No such file or directory</error> <action>die</action> <message>Verify the file exists on the remote server</message> </exception>
After evaluating the method calls, I loop through the exceptions defined by the user.
for my $exception (@exceptions) { if ($@ =~ /$exception->{error}/) { $exception->{action}( &LogMsg( \( "Error", "In action " . "$object_hash{name}: " . "$exception->{message}\n" ) ), "\n" ); } }
The problem I am having is with the $exception->{action} call. In the XML above, the action was to die (don't worry, I check to make sure the user uses warn, die, croak, or carp; that is all I allow, for now). The error I receive is that I can't use the string die while strict refs are in place. Am I calling the sub routine correctly? I have exhausted my resources at work. Thank you

Replies are listed 'Best First'.
(tye)Re: calling a sub routine from a scalar
by tye (Sage) on May 16, 2001 at 21:19 UTC

    The best solution in this case is:

    use Carp qw( carp croak ); my %actions= ( die => sub { die @_ }, warn => sub { warn @_ }, carp => \&carp, croak => \&croak, ); # ... $actions{$exception->{action}}->( ... );
    Note that I couldn't find a way to get \&die, \&CORE::die, etc. to work so I went with simple anonymous subs.

            - tye (but my friends call me "Tye")
      I can't believe I didn't think of that. It works great. Thank you!
      Yes, this is much better too, as long as you have a manageable set of subroutines to call ++

                      - Ant
Re: calling a sub routine from a scalar
by suaveant (Parson) on May 16, 2001 at 20:39 UTC
    &{$exception->{action}}(args); should do fine

    Update You can also do

    local(*foo) = \&{$exception->{action}}; &foo(args);
    if you want, temprarily globbing your subroutine ref to the name foo... either way works...

    Update2 My bad, just realized I needed \ in front of &{$exception->{action}}; to make it work... all fixed
                    - Ant

      Actually, the problem with this is $exception->{action} cannot be dereferenced, as it is a string.
        but perl can call a subroutine by name from a string, or a variable, if you do ${'foo'}, perl sees a string so tries to look at the value of $foo. Same thing goes for subroutines... slower, but very handy.
                        - Ant
Re: calling a sub routine from a scalar
by Hot Pastrami (Monk) on May 16, 2001 at 20:37 UTC
    You'd probably need to eval() the string, wouldn't you? Something like this:
    eval qq{$exception->{action}( &LogMsg( \( "Error", "In action " . "$ob +ject_hash{name}: " . "$exception->{message}\n")), "\n")};


    Hot Pastrami
      eval is overkill, and in this case die would kill the eval, not the perl script, which probably isn't what is wanted... probably
                      - Ant