Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

executing subroutines via variable

by Angel (Friar)
on Nov 19, 2002 at 16:44 UTC ( [id://214178]=perlquestion: print w/replies, xml ) Need Help??

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

I have a script that I would like to be able to have a seperate library of perl commands that would be called when a script executes a certain portion and a variable comes up.

Normally what I would do is
if( $var1 eq "value X" ) { #code }
What if you won't know the variable name so that if a variable ( like in a hash ) comes up it gets evaluated and thena sub containing the varname gets executed
if( $do_additional_test{ $var1 } eq "true" ) { &additional_test_module::$var1( object_vars{ $var1 ) ); )

Replies are listed 'Best First'.
Re: executing subroutines via variable
by Kanji (Parson) on Nov 19, 2002 at 17:16 UTC

    Although it's tempting to use eval in a situation like this, I prefer (ab)using coderefs, either by employing a hash of anonymous subs (rather than subs proper)...

    package atm; my %code = ( var1 => sub { print 1 }, var2 => sub { print 2 }, # ... varN => sub { print N }, ); package main; if ( exists $atm::code{$varN} ) { $atm::code{$varN}->( object_vars($var1) ); } else { # no matching sub }

    ... or testing for the existance of the sub you want to run with can, and executing the coderef it returns.

    if ( my $sub = atm->can($varN) ) { $sub->( object_vars($varN) ); } else { # no matching sub }

        --k.


Re: executing subroutines via variable
by dakkar (Hermit) on Nov 19, 2002 at 17:21 UTC

    You can do that (see perlref):

    ('additional_test_module::'.$var1)->(object_vars($var1));

    But I think you don't want to.

    There are some problems with the approach:

    • It doesn't work under 'strict' (and you are using strict, aren't you?)
    • It can blow up in your face if the variable contains something strange (like, spaces...)
    • It's ugly ;-)

    A better approach is:

    our %subs=('value X'=>\&module::subX, 'value Y'=>\&module::subY, 'somethingelse' => \&module::else); $var=get_the_var(); if (test($var)) { if (exists $subs{$var}) { $subs{$var}->(object_vars($var)) } else { signal_error($var) } }

    This stores all known subs in a hash, then calls the right one.

    Oh, I'm assuming that when you say "don't know the variable name" you mean the "value".

    If you really don't know the possible values of the var, or the possible subs to call, then you have other problems than to worry about 'strict', so you can go with my first code, and in the meantime re-design the system ;-)))

    -- 
            dakkar - Mobilis in mobile
    
Re: executing subroutines via variable
by broquaint (Abbot) on Nov 19, 2002 at 17:27 UTC
    This sounds like a good situation for a dispatch table e.g
    my $dispatch = { foo => \&foo, bar => sub { print "an anon sub\n" }, baz => \&Package::function };
    Yes a dispatch table would be poifict.

    <cough>
    The hackish solution would be

    my %dispatch = map { $_ => \&{$hash{$_}} } keys %hash;
    And definitely for the likes of obfu. Ahem.
    </cough>

    HTH

    _________
    broquaint

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (9)
As of 2024-04-18 11:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found