Как выполнить функции из пакетов, используя ссылку на функцию в Perl? - PullRequest
5 голосов
/ 08 мая 2011

Я хотел использовать ссылку на функцию для динамического выполнения функций из других пакетов.

Я некоторое время пробовал разные решения для этой идеи, и, похоже, ничего не получалось!Итак, я подумал о том, чтобы задать этот вопрос, и, пытаясь это сделать, решение сработало! , но я не уверен, что это правильный способ сделать это: он требует ручной работы и немного "хакерский",Можно ли его улучшить?

  1. Пакет для поддержки необходимой функциональности

    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.Служебный скрипт должен использовать пакет, используя ссылку на функцию

    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');
    }

Но теперь эта техника, похоже, работает!Тем не менее, есть ли способ улучшить его?

Ответы [ 2 ]

4 голосов
/ 09 мая 2011

Вы можете использовать can. Подробнее см. perldoc UNIVERSAL.

use strict;
use warnings;
require Module;

sub ExecuteCommand {
    my ($InputCommand, @Arguments) = @_;
    if (my $ref = Module->can($InputCommand)) {
        $ref->(@Arguments);
    }
    # ...
}
0 голосов
/ 09 мая 2011

Вы создали довольно стандартную реализацию для использования хеша в качестве таблицы отправки.Если это твое намерение, я не вижу причин делать больше, чем немного почистить.can - хорошая альтернатива, если вы пытаетесь построить что-то в OO, но это не обязательно, если все, что вам нужно, это таблица поиска команд.

Вот версия, которая а) является исполняемым Perlкак есть (ваша попытка пометить комментарии с помощью // в версии вопроса является синтаксической ошибкой; в Perl // - это оператор «определен или» 5.10 и выше, не aмаркер комментария) и б) имеет более сильный акцент:

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});
}
...