How to execute functions from packages using function reference in perl?
I wanted to use function reference for dynamically executing functions from other packages.
I have been trying different solutions for a while for the idea and nothing seemed to work! So, i thought of asking this question and while attempting to do so, solution worked! but I'm not sure if it's the correct way to do so: it requires manual work and is a bit "hacky". Can it be improved?
A package to support required functionality
package Module; # $FctHash is intended to be a Look-up table, on-reception # of command.. execute following functions $FctHash ={ 'FctInitEvaluate' => \&FctInitEvaluate, 'FctInitExecute' => \&FctInitExecute }; sub FctInitEvaluate() { //some code for the evalute function } sub FctInitExecute() { //some code for the execute function } 1;
2. Utility Script needs to use the package using function reference
use strict;
use warnings 'all';
no strict 'refs';
require Module;
sub ExecuteCommand()
{
my ($InputCommand,@Arguments) =@_;
my $SupportedCommandRefenece = $Module::FctHash;
#verify if the command is supported before
#execution, check if the key is supported
if(exists($SupportedCommandRefenece->{$InputCommand}) )
{
// execute the function with arguments
$SupportedCommandRefenece->{$InputCommand}(@Arguments开发者_开发技巧);
}
}
# now, evaluate the inputs first and then execute the function
&ExecuteCommand('FctInitEvaluate', 'Some input');
&ExecuteCommand('FctInitExecute', 'Some input');
}
But now, this technique seems to work! Still, is there a way to improve it?
You can use can
. Please see perldoc UNIVERSAL
for details.
use strict;
use warnings;
require Module;
sub ExecuteCommand {
my ($InputCommand, @Arguments) = @_;
if (my $ref = Module->can($InputCommand)) {
$ref->(@Arguments);
}
# ...
}
You've built a fairly standard implementation for using a hash as a dispatch table. If that's your intention, I don't seen any reason to do more than clean it up a little. can
is a good alternative if you're attempting to build something OO-ish, but that's not necessary if all you're after is a command lookup table.
Here's a version that a) is runnable Perl as it stands (your attempt to mark comments with //
in the question's version is a syntax error; in Perl, //
is the 5.10-and-higher "defined-or" operator, not a comment marker) and b) has more of a perlish accent:
Module.pm
package Module;
use strict;
use warnings;
use 5.010;
our $function_lookup = {
FctInitEvaluate => \&init_evaluate,
FctInitExecute => \&init_execute,
};
sub init_evaluate {
say 'In init_evaluate';
}
sub init_execute {
say 'In init_execute';
}
1;
script.pl
#!/usr/bin/env perl
use strict;
use warnings;
require Module;
execute_command('FctInitEvaluate', 'Some input');
execute_command('FctInitExecute', 'Some input');
sub execute_command {
my ($input_command, @arguments) = @_;
$Module::function_lookup->{$input_command}(@arguments)
if exists($Module::function_lookup->{$input_command});
}
精彩评论