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

I'm writing a database maintenance app whose operation is controlled from a database table. One type of entry in the table allows calling a sub in the program with a specified argument. (The program checks that the table entry is on a list of safe-to-call subs.)

I can think of two ways to dispatch to the code based on what I've read in. One is to use a symbolic reference:

# Suppose $op is the name of the sub, # and $arg is the argument string to pass to it. if (is_a_safe_sub($op)) { no strict 'refs'; $op->($arg) or warn "Error, blah, blah"; }
Another way is to use eval:
if (is_a_safe_sub($op)) { eval "$op($arg)" or warn "Error, blah, blah"; }

I made a hit/miss list that looks like this:

An additional consideration is that the people who'll maintain this aren't very strong in Perl; but I'm not sure which construct would be less confusing.

So, brothers and sisters, I humbly seek your counsel. Which way is better, and why? Is there yet a third way I haven't thought about?

TIA

Replies are listed 'Best First'.
Re: Style question: symref or eval?
by suaveant (Parson) on Sep 25, 2001 at 20:58 UTC
    Actually, another good way to go is a dispatch table... a hash of keys being the names of your subroutines and the values being references to those subs...
    my %dispatch = ( test1 => \&test1, test2 => \&test2, etc.. ); if(exists $dispatch{$op}) { $dispatch{op}->($arg); }
    that may not be exactly right, but it gives the idea...

    also, you can check the definedness of subroutines...

    if(defined &$op)
    but most people would cringe at this being a symbol table lookup.... dispatch table is a very common way to go about this...

                    - Ant
                    - Some of my best work - Fish Dinner

(tye)Re: Style question: symref or eval?
by tye (Sage) on Sep 25, 2001 at 21:24 UTC

    Well, I'd strongly discourage the use of stringy eval for this. The only point I'll conceed in favor of it is that it is probably easier to understand by people who aren't qualified to maintain your code. If you want to trap dieing code, then wrap blocky eval around the code in question.

    Also note that you'd want eval "$op(\$arg)" instead of what you wrote.

    In the spirit of DIMTOWDIT, you can also do:

    @_= ($arg); goto &$sub;

            - tye (but my friends call me "Tye")
Re: Style question: symref or eval?
by dragonchild (Archbishop) on Sep 25, 2001 at 20:58 UTC
    Why do you have to turn of strict refs when using a sub-ref? I've never had to...

    Assuming the people maintaining your code know references, a sub-ref is what I'd reccomend as being clearer and easier to maintain.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

      I think he is using a string... not a ref to a sub...

      Update - yeah

      # Suppose $op is the name of the sub,

                      - Ant
                      - Some of my best work - Fish Dinner

        Duh! I thought $op was a hashref of subrefs. *smacks forehead*

        Listen to suaveant ... he said what I was trying to say. ;-)

        ------
        We are the carpenters and bricklayers of the Information Age.

        Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

Re: Style question: symref or eval?
by VSarkiss (Monsignor) on Sep 25, 2001 at 22:30 UTC

    Thanks, everyone. I actually started with a dispatch table as suaveant suggests, but abandoned that for other reasons. I may go back to it -- thanks for the reminder.

    For the moment tye's comment clinched it for me: I'm staying with the symref.

    (Note to self: use goto SUB in some devious way in the future.)